在这个脚本中我们有一个脚本 trap.sh
#!/bin/bash
trap "echo trapped" EXIT
exit 0
和test.sh。如果 test.sh 像
#!/bin/bash
. trap.sh
或者
#!/bin/bash
./trap.sh | :
陷阱工程
但是如果 test.sh 就像
#!/bin/bash
. trap.sh | :
陷阱没有用。
有人知道这是为什么吗?
我修改trap.sh
为包含该xtrace
选项。
#!/bin/bash
set -x
trap 'echo trapped' EXIT
exit 0
trap.sh
作为脚本运行会产生
~ $ ./trap.sh | 猫 + 陷阱 '回声被困' 退出 + 出口 0 + 回声被困
首先采购它,但是会产生
~ $ . trap.sh | cat
++ trap 'echo trapped' EXIT
++ exit 0
这表明trap
在更深的子shell中执行(为什么,我不知道),并且陷阱本身从未执行(我在第二个实验中通过在touch
陷阱中输入文件而不是仅仅回显来确认,以防万一是继承标准输出的问题;该文件从未被触及)。
我的猜测是,根据手册页中命令描述中的这句话,在执行命令EXIT
之前以某种方式忽略了信号:source
trap
进入 shell 时忽略的信号不能被捕获或重置。
结果,trap
命令被执行,但陷阱本身从未注册,因此不会触发。
最好将您的测试命令更改为. trap.sh|cat
(trap.sh
无法显示标准输出:
)。但即使这样也没有输出,所以你是对的:陷阱没有工作。这一定是 bash 中的错误,应该报告给维护人员。
有趣的是,当我们echo $$
从脚本 trap.sh 内部时,我们看到它是由执行整个管道的同一个 shell 执行的. trap.sh|cat
,这与手册中的说法相矛盾:管道中的每个命令都作为一个单独的进程执行(即,在一个子壳)。 这是一个谬论,请参阅评论。也许这与一些优化以最小化子外壳创建有关,但这只是猜测。
管道左侧的命令在子 shell 中运行:
exit | grep
出口信号似乎没有传播到子shell。
trap 'echo T >&2' EXIT ; (exit) # Nothing.