shell编程,信号的捕获修改和移除,trap命令,在脚本中处理信号
常见的Linux信号:
信号 | 值 | 描述 |
1 | SIGHUP(signal hang-up) | 挂起进程 |
2 | SIGINT(signal interrupt) | 终断进程 Ctrl+C |
3 | SIGQUIT(signal quit) | 停止进程 |
9 | SIGKILL(signal kill) | 无条件终止进程 |
15 | SIGTERM(signal terminating) | 尽可能终止进程 |
17 | SIGSTOP(signal stop) | 无条件停止进程,但不是终止进程 |
18 | SIGTSTP(signal stop terminating) | 停止或暂停进程,但不终止进程 Ctrl+Z |
19 | SIGCONT(signal continue) | 继续运行停止的进程 |
结束进程:
Ctrl + C 会提前结束进程
例:sleep 100
^C
在进程结束之前按下Ctrl+C键,这样就给进程发送了一个SIGINT的终止进程信号,程序就会提前终止。
暂停进程/将进程移至后台:
Ctrl + Z 向程序发送一个SIGTSTP的暂停进程信号,程序会暂停运行,单任然保留在内存中。
例:sleep 100
^Z
程序已经暂停,可以用kill命令杀死进程,例:kill -9 2456
查看已经停止的作业 ps -l
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 S 0 2432 2428 0 80 0 - 27075 wait pts/0 00:00:00 bash
0 T 0 2490 2432 0 80 0 - 25226 signal pts/0 00:00:00 sleep
4 R 0 2491 2432 0 80 0 - 27031 - pts/0 00:00:00 ps
这个kill命令会发送一个SIGKILL信号,回车一下就可以显示已经被杀死的进程提示消息。
注意:在S列中ps命令将已经停止作业的状态显示为T。
捕获信号:
trap commands signals 捕获信号执行命令,捕获的signals信号不再由shell处理,而是交由本地处理
例:
trap "echo ' I have trapped Ctrl+C'" SIGINT
for (( a = 1 ; a < 10 ; a++ ))
do
sleep 1
echo $a
done
这样每次使用Ctrl+C都会执行由trap命令指定的命令,而不是shell处理该信号
捕获脚本退出信号:
trap "echo goodbay..." EXIT 当脚本退出或通过Ctrl+C发出的SIGINT退出信号时,都能捕获到退出信号,并执行trap后面的命令
trap "echo goodbay..." EXIT
for (( a = 1 ; a < 10 ; a++ ))
do
sleep 1
echo $a
done
修改信号捕获:
在脚本的不同位置进行不同的捕获,只要重新使用带有新选项的trap命令即可。
例:
trap "echo ' Ctrl+C is trapped'" SIGINT
for (( a = 1; a < 10 ; a++))
do
sleep 1
echo $a
done
trap "echo ' modified the trap!'" SIGINT
for (( a = 1; a < 10; a++ ))
do
sleep 1
echo $a
done
在执行第一个循环时使用Ctrl+C时执行的是第一个trap命令,第二个循环时执行的是第二个trap命令。
移除信号捕获:
trap -- SIGINT 使用“--”来移除捕获信号命令,或者使用“-”来恢复信号的默认行为,两种方法都可以
例:
trap "echo ' Ctrl+C is trapped'" SIGINT
for (( a = 1; a < 10 ; a++))
do
sleep 1
echo $a
done
trap -- SIGINT
for (( a = 1; a < 10; a++ ))
do
sleep 1
echo $a
done
第一个循环时因为SIGINT信号被捕获没有终止脚本,执行到第二个循环时由于已经删除了信号捕获所以发送SIGINT信号终止了脚本