[root@linuxidc ~]# trap 'echo caught the TERM signal' TERM [root@linuxidc ~]# kill $BASHPID caught the TERM signal
再查看已设置的陷阱,之前设置为忽略TERM信号的陷阱已经被覆盖。
[root@linuxidc ~]# trap trap -- '' SIGINT trap -- 'echo caught the TERM signal' SIGTERM trap -- '' SIGTSTP trap -- '' SIGTTIN trap -- '' SIGTTOU
(4).重置针对INT和TERM这两个信号的陷阱为初始状态。
[root@linuxidc ~]# trap - SIGINT SIGTERM [root@linuxidc ~]# trap trap -- '' SIGTSTP trap -- '' SIGTTIN trap -- '' SIGTTOU
(5).在脚本中设置一个能忽略CTRL+C和SIGTERM信号的陷阱。
[root@linuxidc ~]# cat trap1.sh #!/bin/bash # script_name: trap1.sh # trap '' SIGINT SIGTERM sleep 10 echo sleep success
当执行该脚本后,将首先陷入睡眠状态,按下CTRL+C将无效。仍会执行完所有的命令。
[root@linuxidc ~]# ./trap1.sh ^C^C^C^Csleep success
(6).布置一个当脚本中断时能清理垃圾并退出立即脚本的陷阱。
[root@linuxidc ~]# cat trap1.sh #!/bin/bash # script_name: trap1.sh # trap 'echo trap handling...;rm -rf /tmp/$BASHPID$BASHPID;echo TEMP file cleaned;exit' SIGINT SIGTERM SIGQUIT SIGHUP mkdir -p /tmp/$BASHPID$BASHPID/ touch /tmp/$BASHPID$BASHPID/{a.txt,a.log} sleep 10 echo first sleep success sleep 10 echo second sleep success
这样,无论是什么情况中断(除非是SIGKILL),脚本总能清理掉临时垃圾。
1.3 布置完美陷阱必备知识(1).陷阱的守护对象是shell进程本身,不会守护shell环境内的子进程。但如果是信号忽略型陷阱,则会守护整个shell进程组使其忽略给定信号。
以下面这个脚本为例,设置的陷阱会捕捉到SIGING和SIGTERM两个信号,捕捉到信号时将输出陷阱做出处理的时间点。
[root@linuxidc ~]# cat trap2.sh #!/bin/bash # script_name: trap2.sh # trap 'echo trap_handle_time: $(date +"%F %T")' SIGINT SIGTERM echo time_start: $(date +"%F %T") sleep 10 echo time_end1: $(date +"%F %T") sleep 10 echo time_end2: $(date +"%F %T")
执行该脚本,并另开一个会话窗口,杀死trap2.sh脚本。
[root@linuxidc ~]# ./trap2.sh [root@linuxidc ~]# killall -s SIGTERM trap2.sh
执行结果如下。
time_start: 2017-08-14 12:59:23 trap_handle_time: 2017-08-14 12:59:33 time_end1: 2017-08-14 12:59:33 time_end2: 2017-08-14 12:59:43
结果中的trap_handle_time证明,脚本所在shell进程收到SIGTERM信号后,trap成功进行了处理。如果细心的话,会发现trap处理的时间正好是10秒之后,这并不是因为正好10秒之后才发送SIGTERM信号,而是因为trap就是这么工作的,这是另一个需要注意的点,稍后见下文的(2)。
再次执行脚本,在另个会话窗口下杀死脚本中正在运行的sleep进程和trap2.sh脚本所在进程。
[root@linuxidc ~]# ./trap2.sh [root@linuxidc ~]# killall -s SIGTERM sleep ;sleep 3; killall -s SIGINT trap2.sh # 另一个会话终端下执行此命令
最终将返回如下结果:
time_start: 2017-08-14 12:23:06 Terminated # 接收到对sleep发送的SIGTERM信号 time_end1: 2017-08-14 12:23:09 # 没有trap_handle_time,陷阱没有守护sleep进程 trap_handle_time: 2017-08-14 12:23:19 # shell进程本身收到了SIGINT信号,并被陷阱处理了 time_end2: 2017-08-14 12:23:19