目录
trap的基础概念
定义一个trap
忽略信号
重置信号
trap的实例
清理临时文件
清理脚本中的后台进程
采坑点
快捷键:CTRL+(C、Z、\):对于脱离了终端的后台进程无效
接收到信号后,会等待正在执行的前台任务完成后去触发信号处理程序。原因是:shell认为前台进程都是重要任务
信号守护的范围
CTRL+C和SIGINT不等价:前者发INT给shell及其内所有子进程,后者只发送给shell
交互式shell默认会自动忽略TERM信号。在任何情况下,都会忽略QUIT信号
[root@15:14:15 /opt/shellTest]#trap -p [root@15:14:17 /opt/shellTest]# [root@15:14:18 /opt/shellTest]# [root@15:14:18 /opt/shellTest]#trap 'echo traped' INT [root@15:18:06 /opt/shellTest]# [root@15:18:07 /opt/shellTest]# [root@15:18:07 /opt/shellTest]#trap -p trap -- 'echo traped' SIGINT
这个意思就是说当按下Ctrl +c 时输出 traped
可以以列表的形式去定义
忽略TERM信号
忽略INT信号
经常在脚本中会创建文件然后执行结束之后删除,但是当脚本在删除前发生异常,则就会有临时文件产生。如何解决这个问题呢?
捕获异常并触发删除脚本达到此目的。
#!/bin/bash trap 'echo traped;rm -rf $tmp_dir;exit 1' INT HUP QUIT TERM tmp_dir=/tmp/$BASHPID mkdir -p $tmp_dir touch $tmp_dir/{a..d}.log echo "$tmp_dir" ls -l $tmp_dir sleep 5s rm -rf $tmp_dir echo "over"
注意可以使用trap 'echo traped;rm -rf $tmp_dir;exit 1' EXIT
但是不推荐,因为需要程序员去考虑EXIT是哪种退出,而INT HUP QUIT TERM是明确的退出信号。
一般trap的action中要exit 1. 这个是退出状态码,可以自己定义并作出相应的动作,例如报警...
当脚本脱离终端运行后,即使你发送INT信号,还是会一直输出。
看一个小例子
#!/bin/bash while true;do sleep 1s echo hhahha done & sleep 3
主进程等待3s之后,将while true进行后台运行。即使发送INT信号也没有用。使用killall bash才可以停下。
此处需要注意一定要取消刚才定义的trap TERM才能生效。
#!/bin/bash function signal_hangdle { echo trapped kill $pid exit 1 } #trap 'signal_handle' EXIT sleep 10s & pid=$! sleep 20s & pid="$! $pid" sleep 5s ~ ~
结果:
使用trap INT的结果:
trap EXIT:
问题点: 脚本中需要不断收集进程id,如果有10个sleep那就需要收集后台进程ID。
man一下kill 的用法 0 代表进程组,那直接kill 0就可以免去收集后台进程ID
结果:
killall bash也是基于此才不会关闭当前终端这个shell