shell脚本中如何进行信号的捕捉
本篇文章给大家分享的是有关shell脚本中如何进行信号的捕捉,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。
trap从字面意思看就是就是陷阱的意思但是在shell脚本中trap时专门捕捉kill -9,kill -15,CTRL+C等信号的。
1、查看所有可用的信号
trap -l或kill -l即可
[root@linux1 ~]# kill -l63) SIGRTMAX-1 64) SIGRTMAX [root@linux1 ~]# trap -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR111) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM......
2、常见的信号如下:
Signal Value Comment─────────────────────────────SIGHUP 1 终止进程,特别是终端退出时,此终端内的进程都将被终止SIGINT 2 中断进程,几乎等同于sigterm,会尽可能的释放执行clean-up,释放资源,保存状态等(CTRL+C)SIGQUIT 3 从键盘发出杀死(终止)进程的信号SIGKILL 9 强制杀死进程,该信号不可被捕捉和忽略,进程收到该信号后不会执行任何clean-up行为,所以资源不会释放,状态不会保存SIGTERM 15 杀死(终止)进程,几乎等同于sigint信号,会尽可能的释放执行clean-up,释放资源,保存状态等SIGSTOP 19 该信号是不可被捕捉和忽略的进程停止信息,收到信号后会进入stopped状态SIGTSTP 20 该信号是可被忽略的进程停止信号(CTRL+Z)
真正的信号名字不是SIGXXX,而是去除SIG后的单词,每个信号还有对应的代号
比如向PID为12345的进程发起1信号
kill -1 12345kill -HUB 12345kill -SIGHUB 12345
3、trap的选项
trap -l列出当前系统支持的信号列表,上面已经使用过,根kill -l一样
trap -p等价于trap,查看shell已经布置好的陷阱
可以看到shell默认有三个陷阱,表示忽略20,21,22信号
[root@linux1 ~]# traptrap -- '' SIGTSTPtrap -- '' SIGTTINtrap -- '' SIGTTOU
4、陷阱捕捉到信号后干嘛
忽略信号
捕捉到信号后做相应的处理。主要是清理一些脚本创建的临时文件,然后退出。
5、设置一个可以忽略CTRL+C和15信号的陷阱
CTRL信号对应的是SIGINT 15信号对应的是SIGTERM
[root@linux1 ~]# trap '' SIGINT SIGTERM[root@linux1 ~]# traptrap -- '' SIGINTtrap -- '' SIGTERMtrap -- '' SIGTSTPtrap -- '' SIGTTINtrap -- '' SIGTTOU
这样,当前shell就不能被kill -15杀死
6、设置一个陷阱,捕捉到-15信号时,就打印“我抓到你啦~”
[root@linux1 ~]# trap 'echo "我抓到你啦~"' TERM[root@linux1 ~]# traptrap -- '' SIGINTtrap -- 'echo "我抓到你啦~"' SIGTERMtrap -- '' SIGTSTPtrap -- '' SIGTTINtrap -- '' SIGTTOU
效果,当我对当前bash发起kill -15信号时就打印出来了
[root@linux1 ~]# echo $$8827[root@linux1 ~]# kill -15 8827我抓到你啦~[root@linux1 ~]# kill -15 8827我抓到你啦~[root@linux1 ~]# kill -15 8827我抓到你啦~
7、在脚本中设置一个能忽略CTRL+C和CTRL+Z信号的脚本
CTRL+C是2信号,即SIGINT
CTRL+Z是20信号,即SIGTSTP
脚本:
脚本沉睡10s,然后打印success,脚本忽略INT和TSTP信号
[root@linux1 ~]# cat trap.sh#!/bin/bashtrap '' SIGINT SIGTSTPsleep 10echo success
效果:
CTRL+C也不能阻止我睡觉
[root@linux1 ~]# bash trap.sh ^C^C^Z^Z^C^C^Z^Zccc^Z^Z^Z^C^C^Csuccess
8、布置一个当脚本被终端时能清理垃圾并立即退出脚本的陷阱
脚本如下:
[root@linux1 ~]# cat trap1.sh#!/bin/bashtrap 'echo trap handing...;rm -rf /tmp/$BASHPID;echo TEMP files cleaned;exit' SIGINT SIGTERM SIGQUIT SIGHUPmkdir -p /tmp/$$/touch /tmp/$$/{a..c}.txtsleep 10echo first sleep successsleep 10echo second sleep success
这样,脚本除了SIGKILL信号(kill -9),总能清理掉临时垃圾
效果
刚开始一直不能终止,后来执行了下trap发现前面shell自己设置了一个忽略CTRL+C的陷阱,退出shell重进即可
[root@linux1 ~]# bash trap1.sh ^Ctrap handing...TEMP files cleaned
9、陷阱的守护对象
陷阱的守护对象是shell进程本身,不会守护shell环境内的子进程。但如果是信号忽略型陷阱,则会守护整个shell进程组使其忽略给定信号。
[root@linux1 ~]# cat trap2.sh #!/bin/bashtrap 'echo trap_handle_time: $(date +"%F %T")' SIGINT SIGTERMecho time_start: $(date +"%F %T")sleep 10echo time_end1: $(date +"%F %T")sleep 10echo time_end2: $(date +"%F %T")#执行脚本后,新开终端使用kill -15杀死它[root@linux1 ~]# killall -s SIGTERM trap2.sh#查看输出情况[root@linux1 ~]# ./trap2.sh time_start: 2019-08-27 10:43:48trap_handle_time: 2019-08-27 10:43:58time_end1: 2019-08-27 10:43:58time_end2: 2019-08-27 10:44:08
可以发现,kill执行完后,屏幕没有立即打印trap_handle,而是等sleep 10运行完后才打印的。sleep进程都被忽略型trap守护了
只要是向shell进程发送的信号,都会等待当前正在运行的命令结束后才处理信号,然后继续脚本向下运行。(实际上,只有当shell脚本中正在执行的操作是信号安全的系统调用时,才会出现信号无法中断进程的情况,而在shell下的各种命令,我们是没法直接知道哪些命令中正在执行的系统调用是系统调用的)。
但sleep命令发起的sleep()调用,是一个信号安全的,所以上面脚本中执行sleep的过程中,信号不会直接中断它们的运行,而是等待它运行完之后再执行信号处理命令。
10、如果shell中针对某信号设置了陷阱,则该shell进程接收到该信号时,会等待其内正在运行的命令结束才开始处理陷阱
11、CTRL+C和SIGINT不是等价的。当某一时刻按下CTRL+C,它是在向整个当前运行的进程组发送SIGINT信号。对shell脚本来说,SIGINT不仅发送给shell脚本进程,还发送给脚本中当前正在运行的进程
[root@linux1 ~]# cat trap2.sh #!/bin/bashtrap 'echo trap_handle_time: $(date +"%F %T")' SIGINT SIGTERMecho time_start: $(date +"%F %T")sleep 10echo time_end1: $(date +"%F %T")sleep 10echo time_end2: $(date +"%F %T")#执行脚本后,立马CTRL+C[root@linux1 ~]# bash trap2.sh time_start: 2019-08-27 10:20:53^Ctrap_handle_time: 2019-08-27 10:20:54time_end1: 2019-08-27 10:20:54time_end2: 2019-08-27 10:21:04
可以发现,CTRL+C后,不仅trap进行处理了,sleep也立马结束了;说明CTRL+C不仅让脚本进程收到了SIGINT信号,也让当前进程收到了SIGINT信号
以上就是shell脚本中如何进行信号的捕捉,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注编程网行业资讯频道。
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341