当前位置:   article > 正文

shell中的信号捕获trap(shell 进阶)_shell trap

shell trap

 

目录

trap的基础概念 

定义一个trap 

 忽略信号 

 重置信号

 trap的实例

清理临时文件

清理脚本中的后台进程

采坑点

快捷键:CTRL+(C、Z、\):对于脱离了终端的后台进程无效

接收到信号后,会等待正在执行的前台任务完成后去触发信号处理程序。原因是:shell认为前台进程都是重要任务

 信号守护的范围

CTRL+C和SIGINT不等价:前者发INT给shell及其内所有子进程,后者只发送给shell

交互式shell默认会自动忽略TERM信号。在任何情况下,都会忽略QUIT信号


trap的基础概念 

定义一个trap 

  1. [root@15:14:15 /opt/shellTest]#trap -p
  2. [root@15:14:17 /opt/shellTest]#
  3. [root@15:14:18 /opt/shellTest]#
  4. [root@15:14:18 /opt/shellTest]#trap 'echo traped' INT
  5. [root@15:18:06 /opt/shellTest]#
  6. [root@15:18:07 /opt/shellTest]#
  7. [root@15:18:07 /opt/shellTest]#trap -p
  8. trap -- 'echo traped' SIGINT

这个意思就是说当按下Ctrl +c 时输出 traped 

可以以列表的形式去定义

 忽略信号 

忽略TERM信号

 忽略INT信号

 重置信号

 trap的实例

清理临时文件

经常在脚本中会创建文件然后执行结束之后删除,但是当脚本在删除前发生异常,则就会有临时文件产生。如何解决这个问题呢?

捕获异常并触发删除脚本达到此目的。

  1. #!/bin/bash
  2. trap 'echo traped;rm -rf $tmp_dir;exit 1' INT HUP QUIT TERM
  3. tmp_dir=/tmp/$BASHPID
  4. mkdir -p $tmp_dir
  5. touch $tmp_dir/{a..d}.log
  6. echo "$tmp_dir"
  7. ls -l $tmp_dir
  8. sleep 5s
  9. rm -rf $tmp_dir
  10. echo "over"

注意可以使用trap 'echo traped;rm -rf $tmp_dir;exit 1' EXIT

但是不推荐,因为需要程序员去考虑EXIT是哪种退出,而INT HUP QUIT TERM是明确的退出信号。

一般trap的action中要exit 1. 这个是退出状态码,可以自己定义并作出相应的动作,例如报警...

清理脚本中的后台进程

当脚本脱离终端运行后,即使你发送INT信号,还是会一直输出。

看一个小例子

  1. #!/bin/bash
  2. while true;do
  3. sleep 1s
  4. echo hhahha
  5. done &
  6. sleep 3

 主进程等待3s之后,将while true进行后台运行。即使发送INT信号也没有用。使用killall bash才可以停下。

此处需要注意一定要取消刚才定义的trap TERM才能生效。

 

  1. #!/bin/bash
  2. function signal_hangdle {
  3. echo trapped
  4. kill $pid
  5. exit 1
  6. }
  7. #trap 'signal_handle' EXIT
  8. sleep 10s &
  9. pid=$!
  10. sleep 20s &
  11. pid="$! $pid"
  12. sleep 5s
  13. ~
  14. ~

结果: 

 使用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

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/197499
推荐阅读
相关标签
  

闽ICP备14008679号