如果我trap
[针对同一信号]发出内置命令两次,会发生什么?是第二个命令添加到第一个,还是它代替首先?
trap Foo SIGINT
...
trap Bar SIGINT
...
当 SIGINT 发生时,Bash 是只运行,还是也Bar
运行?Foo
或者是其他东西...?
答案1
命令被替换。
联机帮助页指出:
trap [-lp] [[arg] sigspec ...]
The command arg is to be read and executed when the shell
receives signal(s) sigspec. If arg is absent (and there is a
single sigspec) or -, each specified signal is reset to its
original disposition (the value it had upon entrance to the
shell). If arg is the null string the signal specified by each
sigspec is ignored by the shell and by the commands it invokes.
If arg is not present and -p has been supplied, then the trap
commands associated with each sigspec are displayed. If no
arguments are supplied or if only -p is given, trap prints the
list of commands associated with each signal. The -l option
causes the shell to print a list of signal names and their cor‐
responding numbers. Each sigspec is either a signal name
defined in <signal.h>, or a signal number. Signal names are
case insensitive and the SIG prefix is optional.
它注明了the command arg is to be read and executed ...
时期。否则,如果 arg 始终添加到列表中,则无法重置信号处理。
答案2
来自手动的:
trap [-lp] [arg] [sigspec …]
中的命令精氨酸当 shell 收到信号时被读取并执行信号规范。
该描述没有提及任何有关添加到现有命令列表的内容。它继续指定非增量效应精氨酸为空或字符串-
。虽然文本可能没有明确说明命令未添加到列表中,但它从未提及任何此类列表,或从所述列表中删除项目的任何方法。因此,以暗示连续trap
命令添加到列表的方式解释此文本arg
是相当牵强的。
您可以通过检查另一个 shell 的手册来确定。如果 bash 偏离了通常的行为,手册会明确说明。这POSIX标准在这个问题上是明确的:
的行动陷阱应覆盖先前的操作(默认操作或明确设置的操作)。
答案3
我还是找不到文档关于这个问题,但从我的测试来看出现第二个trap
规范完全取代第一个规范。 (即,Bar
将运行,但Foo
不会运行。)
答案4
正如已经回答的那样, trap 命令会替换已经存在的陷阱。如果您确实希望当前的和新的都被执行,我想您可以稍微修改一下:
function overtrap {
trap="$1"
sig=$(echo $2 | tr [a-z] [A-Z])
cur="$(trap -p $sig | sed -nr "s/trap -- '(.*)' $sig\$/\1/p")"
if test ${cur:+x}; then
trap "{ $trap; }; $cur" $sig
else
trap "$trap" $sig
fi
}
调用类似的东西
overtrap 'echo hi' exit
overtrap 'echo ho' exit
会打印
ho
hi
(但我不知道它有多便携。)