为什么陷阱在管道中不起作用

时间:2013-07-19 08:08:36

标签: linux bash shell bash-trap

在这个脚本中 我们有一个脚本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 | :
陷阱不起作用。

有人知道为什么会这样吗?

3 个答案:

答案 0 :(得分:1)

最好将测试命令更改为. trap.sh|cattrap.sh的标准输出无法与:一起显示。但即便如此也没有输出,所以你是对的:陷阱不起作用。这必须是bash中的错误,应该向维护者报告。

有趣的是,当我们从脚本trap.sh内部echo $$时,我们看到它由执行整个管道. trap.sh|cat的同一个shell执行,与手册的声明相矛盾:管道中的每个命令都作为一个单独的进程执行(即,在子shell中)。 这是一个谬论,请参阅注释。也许这与一些优化相关,以最大限度地减少子shell创建,但那只是猜测。

答案 1 :(得分:1)

我修改了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的第二个实验中确认了一个文件int陷阱而不是只是回显,如果标准输出有问题被继承;文件从未被触及过。)

我的猜测是,在执行EXIT命令之前,source信号被忽略,基于手册页中trap命令描述中的这句话:

  

信号被忽略了                 无法捕获或重置shell的条目。

结果,执行trap命令,但陷阱本身从未注册,因此不会触发。

答案 2 :(得分:0)

管道左侧的命令在子shell中运行:

exit | grep

退出sigtrap似乎不会传播到子shell。

trap 'echo T >&2' EXIT ; (exit)    # Nothing.