在这个脚本中 我们有一个脚本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 | :
陷阱不起作用。
有人知道为什么会这样吗?
答案 0 :(得分:1)
最好将测试命令更改为. trap.sh|cat
(trap.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.