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

 

目录

trap的基础概念 

定义一个trap 

 忽略信号 

 重置信号

 trap的实例

清理临时文件

清理脚本中的后台进程

采坑点

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

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

 信号守护的范围

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

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


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

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 

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

可以以列表的形式去定义

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

 忽略信号 

忽略TERM信号

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

 忽略INT信号

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

 重置信号

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

 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才能生效。

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

 

#!/bin/bash
  
function signal_hangdle {
        echo trapped
        kill $pid
        exit 1
}

#trap  'signal_handle' EXIT

sleep 10s &
pid=$!

sleep 20s &
pid="$! $pid"


sleep 5s
~                                                                               
~               

结果: 

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

 使用trap INT的结果:

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

 trap EXIT:

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

问题点: 脚本中需要不断收集进程id,如果有10个sleep那就需要收集后台进程ID。

man一下kill 的用法 0 代表进程组,那直接kill 0就可以免去收集后台进程ID

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

结果:

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

采坑点

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

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

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

 信号守护的范围

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

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

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

 

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

killall bash也是基于此才不会关闭当前终端这个shell

 

上一篇:leetcode 2030. 含特定字母的最小子序列


下一篇:什么样的人,可以在金融市场赚到钱