结果说明脚本中的trap陷阱没有守护shell内的sleep进程,只守护了shell本身。同样也发现了,虽然是在3秒后发送INT信号给脚本进程,但陷阱同样是在10秒之后才开始处理的。
再修改脚本中的陷阱为信号忽略陷阱。
[root@linuxidc ~]# cat ./trap3.sh #!/bin/bash # script_name: trap3.sh # trap '' SIGINT SIGTERM echo time_start: $(date +"%F %T") sleep 10 echo time_end1: $(date +"%F %T") sleep 10 echo time_end2: $(date +"%F %T")
执行trap3.sh,并在另一个会话终端下杀死sleep进程。
[root@linuxidc ~]# ./trap3.sh [root@linuxidc ~]# killall -s SIGTERM sleep;sleep 3;killall -s SIGINT sleep # 另一个会话终端下执行此命令
结果如下。从时间差可以看出,无论是SIGTERM还是SIGINT信号,sleep进程都被忽略型trap守护了。
time_start: 2017-08-14 12:31:54 time_end1: 2017-08-14 12:32:04 time_end2: 2017-08-14 12:32:14
(2).如果shell中针对某信号设置了陷阱,则该shell进程接收到该信号时,会等待其内正在运行的命令结束才开始处理陷阱。
其实(1)中的几个示例的结果已经证明了这一点。只要是向shell进程发送的信号,都会等待当前正在运行的命令结束后才处理信号,然后继续脚本向下运行。
(3).CTRL+C和SIGINT不是等价的。当某一时刻按下CTRL+C,它是在向整个当前运行的进程组发送SIGINT信号。对shell脚本来说,SIGINT不仅发送给shell脚本进程,还发送给脚本中当前正在运行的进程。
所以,如果shell中设置SIGINT陷阱,不仅会终止脚本中当前正在运行的进程,trap还会立即进行对应的处理。
以下面的脚本trap4.sh为例。
[root@linuxidc ~]# cat trap4.sh #!/bin/bash # script_name: trap4.sh # trap 'echo trap_handle_time: $(date +"%F %T")' SIGINT echo time_start: $(date +"%F %T") sleep 10 echo time_end1: $(date +"%F %T") sleep 10 echo time_end2: $(date +"%F %T")
如果使用kill命令向trap4.sh发送信号,正常情况下trap会在当前运行的sleep进程完成后才进行相关处理。但如果是按下CTRL+C,先看结果。
[root@linuxidc ~]# ./trap4.sh time_start: 2017-08-14 13:41:30 ^Ctrap_handle_time: 2017-08-14 13:41:31 time_end1: 2017-08-14 13:41:31 ^Ctrap_handle_time: 2017-08-14 13:41:32 time_end2: 2017-08-14 13:41:32
结果中显示,两次按下CTRL+C后,不仅sleep立刻结束了,trap也立即进行处理了。这说明CTRL+C不仅让脚本进程收到了SIGINT信号,也让当前正在运行的进程收到了SIGINT信号。
需要特别说明的是,如果当前正在运行的进程处在循环内,当该进程收到了终止进程后,仅仅只是立即终止当次进程,而不会终止整个循环,也就是说,它还会继续向下执行后续命令并进入下一个循环。如果此时是使用CTRL+C发送SIGINT,则每次CTRL+C时,trap也会一次次进行处理。