bash下利用trap捕捉信号

我在之前的文章里写了myisam读数据压缩的情况,最近决定把它用在生产环境上,所以避免不了写一个“安全”的处理脚本放在DB服务器上,这就引入了本文所讨论的话题。

我希望这个bash脚本在退出的时候做一些事情,包括:

  1. 它启动的切到后台的job需要被杀死;
  2. 一些临时文件的清理。

在这个脚本里我用到了trap这个命令,关于它,你可以man一下,我这里就不啰嗦了。直接上示例代码:

$ cat test_trap.sh
 
declare -i run_terminate=0
 
trap "run_terminate=1" SIGINT SIGTERM
 
# 启动io监控,IO较大时不进行压缩
vmstat 1 >> ./a.log &
 
while [ ${run_terminate} -eq 0 ]
do
    # 核心代码
    sleep 30
done
 
for pid in $(ps -ef | awk -v p=${$} '{if ($3 == p){print $2}}')
do
    kill -9 ${pid} > /dev/null
done
 
rm -f ./a.log
echo "Terminated."

在上面的代码中,我们捕捉INT信号(CTRL+C)和TERM信号(kill产生)。运行程序:

$ /bin/bash test_trap.sh
 
^C

按照我们预期的,当我CTRL+C退出程序,或者kill进程时,上面的脚本应该停掉vmstat进程,并且删除a.log,输出“Terminated”后退出。

但是,CTRL+C确实按照我们的设想进行了。可kill之后程序并没有任何反应,这是为何?

Google了一遍,天下文章一大抄,相似的例子,却没有人抛出这个问题。思索了半天,幡然醒悟:

  1. kill(killall)命令只是发出一个TERM信号(15),至于这个信号是否被对应进程捕捉并处理了,它并不管;
  2. kill发出的时候,test_trap.sh正在sleep——这个时间有点长(30秒)。

也就是说,等它“睡醒”了,它自然会处理TERM信号的。不信,你多等一会。

Tags: , ,

7 Responses

  1. tangyi 说道:

    标题里多了一个字.

  2. 朋春 说道:

    多谢指正,已改

  3. hoterran 说道:

    最好把SIGHUP也sigprocmask掉,顺便记一下日志

    trap ‘echo “receive sig”>>xxx.log’ 1 3 15

  4. 朋春 说道:

    我的程序是以nohup来启动的,不希望终端退出时程序也终止掉。不过这个建议非常好;写日志也是一个很好的建议。谢谢

  5. 广东知道网 说道:

    我比较菜,有点看不懂“`

  6. 半醒 说道:

    你好
    能将feed改为全文输出么?

  7. 二手笔记本 说道:

    真的,我好菜的,看不懂哦…..看来我还得有待提高啊。….

Leave a Reply

*