bash trap''vs trap函数传递信号

时间:2016-08-12 01:34:36

标签: bash signals kill bash-trap process-group

我对使用陷阱将信号转发到子进程感到困惑。说我有两个脚本:

a.sh

#!/bin/bash

# print the process id
echo $$

cleanup() {
    rv=$?
    echo "cleaning up $rv"
    exit
}

sleep 5
trap '' SIGTERM # trap cleanup SIGTERM
echo 'cant stop wont stop'
./b.sh
echo 'can stop will stop'
trap - SIGTERM
sleep 4
echo 'done'

b.sh

#!/bin/bash
sleep 4;
echo 'b done'

如果我执行a.sh然后从另一个窗口使用kill -- -PGID终止进程组,SIGTERM将被忽略,不会传递给b.sh。但如果我trap cleanup SIGTERM,则SIGTERM会通过并终止b.sh。为什么我的陷阱在一个案例而不是另一个案件中传递信号?

2 个答案:

答案 0 :(得分:1)

来自trap man page

  

陷阱[行动条件......]

     

如果action为null(""),如果出现,shell将忽略每个指定的条件。

因此,当您执行TRAP '' SIGTERM时,将忽略SIGTERM条件。尝试使用空格值,看看它是否有效:

sleep 5
trap ' ' SIGTERM # Note the space (' ')!!

echo 'cant stop wont stop'
./b.sh

echo 'can stop will stop'
trap - SIGTERM

sleep 4
echo 'done'

答案 1 :(得分:1)

这很有趣。引用man 7 signal

  

通过fork(2)创建的子级继承其父级信号处置的副本。在execve(2)期间,处理信号的处置被重置为默认值;被忽略信号的处理方式保持不变。

在您的情况下,孩子总是因为处于同一个流程组而收到TERM。问题是,它有什么作用。

当父忽略 TERM时,按照上述规则,孩子也一样,所以孩子幸存下来。当父捕获 TERM时,子项的处理程序将被重置,它将作为默认操作而死亡。