我对使用陷阱将信号转发到子进程感到困惑。说我有两个脚本:
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
。为什么我的陷阱在一个案例而不是另一个案件中传递信号?
答案 0 :(得分:1)
陷阱[行动条件......]
如果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
时,子项的处理程序将被重置,它将作为默认操作而死亡。