shell脚本中如何进行信号的捕捉

发布时间:2022-01-24 10:21:03 作者:柒染
来源:亿速云 阅读:620

本篇文章给大家分享的是有关shell脚本中如何进行信号的捕捉,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。

trap从字面意思看就是就是陷阱的意思但是在shell脚本中trap时专门捕捉kill -9,kill -15,CTRL+C等信号的。

shell脚本中如何进行信号的捕捉

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) SIGUSR1
11) 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 SIGTSTP
sleep 10echo success

效果:

CTRL+C也不能阻止我睡觉

[root@linux1 ~]# bash trap.sh ^C^C^Z^Z^C^C^Z^Zccc^Z^Z^Z^C^C^C

success

8、布置一个当脚本被终端时能清理垃圾并立即退出脚本的陷阱

脚本如下:

[root@linux1 ~]# cat trap1.sh#!/bin/bashtrap 'echo trap handing...;rm -rf /tmp/$BASHPID;echo TEMP files cleaned;exit' SIGINT SIGTERM SIGQUIT SIGHUP
mkdir -p /tmp/$$/
touch /tmp/$$/{a..c}.txt
sleep 10echo first sleep success
sleep 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:48
trap_handle_time: 2019-08-27 10:43:58
time_end1: 2019-08-27 10:43:58
time_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:54
time_end1: 2019-08-27 10:20:54
time_end2: 2019-08-27 10:21:04

可以发现,CTRL+C后,不仅trap进行处理了,sleep也立马结束了;说明CTRL+C不仅让脚本进程收到了SIGINT信号,也让当前进程收到了SIGINT信号

以上就是shell脚本中如何进行信号的捕捉,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注亿速云行业资讯频道。

推荐阅读:
  1. Linux捕捉信号机制之(signal,kill)、(sig
  2. koa怎么进行错误捕捉和返回

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

shell

上一篇:Linux系统如何安装docker

下一篇:vue-cli-server怎么使用

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》