1

我对将信号转发到带有陷阱的子进程感到困惑。假设我有两个脚本:

#!/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。为什么我的陷阱在一种情况下传递信号而不是另一种情况?

4

2 回答 2

1

trap手册页

陷阱【动作条件……】

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

所以当你执行时TRAP '' SIGTERMSIGTERM条件被忽略。尝试使用空格值,看看它是否有效:

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'
于 2016-08-12T02:44:39.523 回答
1

这是有趣的。报价man 7 signal

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

在您的情况下,孩子总是TERM因为在同一个进程组中而收到。问题是,它用它做什么。

当父母忽略 TERM时,根据上面的规则,孩子也会忽略,所以孩子会幸存下来。当父级捕获 TERM时,子级的处理程序将被重置,并且它将作为默认操作死亡。

于 2016-08-12T04:10:57.480 回答