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

bash trap '' vs trap function passing signals

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

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 然后从另一个 window 使用 kill -- -PGID 终止进程组,SIGTERM 将被忽略并且不会传递给 b.sh。但是,如果我执行 trap cleanup SIGTERM,SIGTERM 通过并终止 b.sh。为什么我的陷阱在一种情况下通过信号而不是另一种情况?

来自trap man page

trap [action condition ...]

If action is null ( "" ), the shell shall ignore each specified condition if it arises.

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

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'

这很有趣。引用 man 7 signal:

A child created via fork(2) inherits a copy of its parent's signal dispositions. During an execve(2), the dispositions of handled signals are reset to the default; the dispositions of ignored signals are left unchanged.

在您的情况下,child 总是会收到 TERM,因为它们位于同一个进程组中。问题是,它有什么用。

当 parent 忽略 TERM 时,根据上面的规则,child 也会忽略 child幸存下来。当parent 捕获 TERM时,child的handler会被重置,默认会死