shell中的信号捕获trap(shell 进阶)
作者:互联网
目录
快捷键:CTRL+(C、Z、\):对于脱离了终端的后台进程无效
接收到信号后,会等待正在执行的前台任务完成后去触发信号处理程序。原因是:shell认为前台进程都是重要任务
CTRL+C和SIGINT不等价:前者发INT给shell及其内所有子进程,后者只发送给shell
交互式shell默认会自动忽略TERM信号。在任何情况下,都会忽略QUIT信号
trap的基础概念
定义一个trap
[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信号
重置信号
trap的实例
清理临时文件
经常在脚本中会创建文件然后执行结束之后删除,但是当脚本在删除前发生异常,则就会有临时文件产生。如何解决这个问题呢?
捕获异常并触发删除脚本达到此目的。
#!/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
结果:
采坑点
快捷键:CTRL+(C、Z、\):对于脱离了终端的后台进程无效
接收到信号后,会等待正在执行的前台任务完成后去触发信号处理程序。原因是:shell认为前台进程都是重要任务
信号守护的范围
CTRL+C和SIGINT不等价:前者发INT给shell及其内所有子进程,后者只发送给shell
交互式shell默认会自动忽略TERM信号。在任何情况下,都会忽略QUIT信号
killall bash也是基于此才不会关闭当前终端这个shell
标签:tmp,shell,进阶,INT,trap,信号,dir 来源: https://blog.csdn.net/MyySophia/article/details/122194021