如何优化网站关键字,如何做网签合同 网站,点击网络怎么做网站,cctv 13新闻频道Linux利用信号与系统中的进程进行通信。你可以通过对脚本进行编程#xff0c;使其在收到特定信号时执行某些命令#xff0c;从而控制shell脚本的操作。
1.重温Linux信号
Linux系统和应用程序可以产生超过30个信号。下表列出了在shell脚本编程时会遇到的最常见的Linux系统信…Linux利用信号与系统中的进程进行通信。你可以通过对脚本进行编程使其在收到特定信号时执行某些命令从而控制shell脚本的操作。
1.重温Linux信号
Linux系统和应用程序可以产生超过30个信号。下表列出了在shell脚本编程时会遇到的最常见的Linux系统信号。
Linux系统信号 信号值描述1SIGHUP挂起hang up进程2SIGINT中断interrupt进程3SIGQUIT停止stop进程9SIGKILL无条件终止terminate进程15SIGTERM尽可能终止进程18SIGCONF继续运行停止的进程19SIGSTOP无条件停止但不终止进程20SIGTSTP停止或暂停pause但不终止进程
在默认情况下bash shell会忽略收到的任何SIGQUIT3信号和SIGTERM15信号因此交互式shell才不会被意外终止。但是bash shell会处理收到的所有SIGHUP1信号和SIGINT2信号。
如果收到了SIGHUP信号比如在离开交互式shell时bash shell就会退出。但在退出之前它会将SIGHUP信号传给所有由该shell启动的进程包括正在运行的shell脚本。
随着收到SIGINT信号shell会被中断。Linux内核将不再为shell分配CPU处理时间。当出现这种情况时shell会将SIGINT信号传给由其启动的所有进程以此告知出现的状况。
你可能也注意到了shell会将这些信号传给shell脚本来处理。而shell脚本的默认行为是忽略这些信号因为可能不利于脚本运行。要避免这种情况可以在脚本中加入识别信号的代码并做相应的处理。
2.产生信号
bash shell允许使用键盘上的组合键来生成两种基本的Linux信号。这个特性在需要停止或暂停失控脚本时非常方便。
1.中断进程
CtrlC组合键会生成SIGINT信号并将其发送给当前在shell中运行的所有进程。通过执行一条需要很长时间才能完成的命令然后按下CtrlC组合键可以对此进行测试
$ sleep 60
^C
$
sleep命令会按照指定的秒数暂停shell操作一段时间然后返回shell提示符。CtrlC组合键会发送SIGINT信号停止shell中当前运行的进程。在超时前60秒按下CtrlC组合键就可以提前终止sleep命令。
2.暂停进程
你也可以暂停进程而不是将其终止。尽管有时这可能比较危险比如脚本打开了一个关键的系统文件的文件锁但它往往可以在不终止进程的情况下使你能够深入脚本内部一窥究竟。
CtrlZ组合键会生成SIGTSTP信号停止shell中运行的任何进程。停止stopping进程跟终止terminating进程不同前者让程序继续驻留在内存中还能从上次停止的位置继续运行。
当使用CtrlZ组合键时shell会通知你进程已经被停止了
$ sleep 60
^Z
[1] Stopped sleep 60
$
方括号中的数字是shell分配的作业号。shell将运行的各个进程称为作业并为作业在当前shell内分配了唯一的作业号。作业号从1开始然后是2依次递增。
如果shell会话中有一个已停止的作业那么在退出shell时bash会发出提醒
$ sleep 70
^Z
[2] Stopped sleep 70
$
$ exit
logout
There are stopped jobs.
$
可以用ps命令查看已停止的作业
$ ps -l
F S UID PID PPID [...] TTY TIME CMD
0 S 1001 1509 1508 [...] pts/0 00:00:00 bash
0 T 1001 1532 1509 [...] pts/0 00:00:00 sleep
0 T 1001 1533 1509 [...] pts/0 00:00:00 sleep
0 R 1001 1534 1509 [...] pts/0 00:00:00 ps
$
在S列进程状态中ps命令将已停止作业的状态显示为T。这说明命令要么被跟踪要么被停止。
如果在有已停止作业的情况下仍旧想退出shell则只需再输入一遍exit命令即可。shell会退出终止已停止作业。
或者如果知道已停止作业的PID那就可以用kill命令发送SIGKILL9信号将其终止
$ kill -9 1532
[1]- Killed sleep 60
$ kill -9 1533
[2] Killed sleep 70
$
每当shell生成命令行提示符时也会显示shell中状态发生改变的作业。“杀死”作业后shell会显示一条消息表示运行中的作业已被“杀死”然后生成提示符。 注意 在某些Linux系统中“杀死”作业时不会得到任何回应。但当下次执行能让shell生成命令行提示符的操作时比如按下Enter键你会看到一条消息表示作业已被“杀死”。 3.捕获信号
你也可以用其他命令在信号出现时将其捕获而不是忽略信号。trap命令可以指定shell脚本需要侦测并拦截的Linux信号。如果脚本收到了trap命令中列出的信号则该信号不再由shell处理而是由本地处理。
trap命令的格式如下
trap commands signals
在trap命令中需要在commands部分列出想要shell执行的命令在signals部分列出想要捕获的信号多个信号之间以空格分隔。指定信号的时候可以使用信号的值或信号名。
下面这个简单的例子展示了如果使用trap命令捕获SIGINT信号并控制脚本的行为
$ cat trapsignal.sh
#!/bin/bash
#Testing signal trapping
#
trap echo Sorry! I have trapped Ctrl-C SIGINT
#
echo This is a test script.
#
count1
while [ $count -le 5 ]
doecho Loop #$countsleep 1count$[ $count 1 ]
done
#
echo This is the end of test script.
exit
$
每次侦测到SIGINT信号时本例中的trap命令都会显示一行简单的文本消息。捕获这些信号可以阻止用户通过组合键CtrlC停止脚本
$ ./trapsignal.sh
This is a test script.
Loop #1
Loop #2
^C Sorry! I have trapped Ctrl-C
Loop #3
^C Sorry! I have trapped Ctrl-C
Loop #4
Loop #5
This is the end of test script.
$
每次使用CtrlC组合键脚本都会执行trap命令中指定的echo语句而不是忽略信号并让shell停止该脚本。 警告 如果脚本中的命令被信号中断使用带有指定命令的trap未必能让被中断的命令继续执行。为了保证脚本中的关键操作不被打断请使用带有空操作命令的trap以及要捕获的信号列表例如 trap SIGINT 这种形式的trap命令允许脚本完全忽略SIGINT信号继续执行重要的工作。 4.捕获脚本退出
除了在shell脚本中捕获信号也可以在shell脚本退出时捕获信号。这是在shell完成任务时执行命令的一种简便方法。
要捕获shell脚本的退出只需在trap命令后加上EXIT信号即可
$ cat trapexit.sh
#!/bin/bash
#Testing exit trapping
#
trap echo Goodbye... EXIT
#
count1
while [ $count -le 5 ]
doecho Loop #$countsleep 1count$[ $count 1 ]
done
#
exit
$
$ ./trapexit.sh
Loop #1
Loop #2
Loop #3
Loop #4
Loop #5
Goodbye...
$
当脚本运行到正常的退出位置时触发了EXITshell执行了在trap中指定的命令。如果提前退出脚本则依然能捕获到EXIT
$ ./trapexit.sh
Loop #1
Loop #2
Loop #3
^CGoodbye...$
因为SIGINT信号并未在trap命令的信号列表中所以当按下CtrlC组合键发送SIGINT信号时脚本就退出了。但在退出之前已经触发了EXIT于是shell会执行trap命令。
5.修改或移除信号捕获
要想在脚本中的不同位置进行不同的信号捕获处理只需重新使用带有新选项的trap命令即可
$ cat trapmod.sh
#!/bin/bash
#Modifying a set trap
#
trap echo Sorry...Ctrl-C is trapped. SIGINT
#
count1
while [ $count -le 3 ]
doecho Loop #$countsleep 1count$[ $count 1 ]
done
#
trap echo I have modified the trap! SIGINT
#
count1
while [ $count -le 3 ]
doecho Second Loop #$countsleep 1count$[ $count 1 ]
done
#
exit
$
修改了信号捕获之后脚本处理信号的方式就会发生变化。但如果信号是在捕获被修改前接收到的则脚本仍然会根据原先的trap命令处理该信号。
$ ./trapmod.sh
Loop #1
^C Sorry...Ctrl-C is trapped.
Loop #2
Loop #3
Second Loop #1
Second Loop #2
^C I have modified the trap!
Second Loop #3
$ 提示 如果在交互式shell会话中使用trap命令可以使用trap -p查看被捕获的信号。如果什么都没有显示则说明shell会话按照默认方式处理信号。 也可以移除已设置好的信号捕获。在trap命令与希望恢复默认行为的信号列表之间加上两个连字符即可。
$ cat trapremoval.sh
#!/bin/bash
#Removing a set trap
#
trap echo Sorry...Ctrl-C is trapped. SIGINT
#
count1
while [ $count -le 3 ]
doecho Loop #$countsleep 1count$[ $count 1 ]
done
#
trap -- SIGINT
echo The trap is now removed.
#
count1
while [ $count -le 3 ]
doecho Second Loop #$countsleep 1count$[ $count 1 ]
done
#
exit
$ 注意 也可以在trap命令后使用单连字符来恢复信号的默认行为。单连字符和双连字符的效果一样。 移除信号捕获后脚本会按照默认行为处理SIGINT信号也就是终止脚本运行。但如果信号是在捕获被移除前接收到的那么脚本就会按照原先trap命令中的设置进行处理
$ ./trapremoval.sh
Loop #1
Loop #2
^C Sorry...Ctrl-C is trapped.
Loop #3
The trap is now removed.
Second Loop #1
Second Loop #2
^C
$
在本例中第一个CtrlC组合键用于提前终止脚本。因为信号是在捕获被移除前接收的所以脚本会按照事先的安排执行trap中指定的命令。捕获随后会被移除再按CtrlC组合键就能提前终止脚本了。