Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 为什么陷阱没有';我不能在管道里工作_Linux_Bash_Shell_Bash Trap - Fatal编程技术网

Linux 为什么陷阱没有';我不能在管道里工作

Linux 为什么陷阱没有';我不能在管道里工作,linux,bash,shell,bash-trap,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 #!/bin/bash . trap.sh | : 陷阱没用 有人知道为什么吗?管道左侧的命令在子shell中运行: exit | gre

在这个脚本中 我们有一个脚本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
#!/bin/bash
. trap.sh | :
陷阱没用


有人知道为什么吗?

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

exit | grep
退出信号陷阱似乎不会传播到子shell

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

最好将测试命令更改为
。trap.sh | cat
(trap.sh的标准输出无法与
一起显示)。但即使这样,也没有输出,所以你是对的:陷阱不起作用。这一定是bash中的一个bug,应该向维护人员报告


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

我修改了
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中执行的(为什么,我不知道),而且trap本身从未执行过(我在第二个实验中通过
touch
在trap中插入一个文件,而不是仅仅回显,以防继承标准输出时出现问题;该文件从未被触碰过)

根据手册页中对
陷阱
命令的描述中的这句话,我猜想在执行
命令之前,
退出
信号会被忽略:

被忽视的信号 无法捕获或重置外壳的入口


因此,执行了
trap
命令,但trap本身从未注册,因此不会启动。

是否有脚本运行时,工作目录(cwd)不在脚本所在的位置?@wallyk不,它不在脚本所在的位置。我注意到了子shell问题。但是当我们打电话的时候。trap.sh |::,我想我们在子shell中调用trap.sh,子shell称为trap,当子shell退出时,trap调用应该像调用/trap.sh |::一样调用。我不明白为什么会有不同的结果。
$
总是计算父shell的进程ID,即使子进程在不同的进程中执行。+1,因为我认为这可能是一个bug。我用
touch trap.fired
替换了echo,以确保这不是标准输出丢失的问题。使用
。trap.sh |::
,该文件未创建。尽管bash手册声明:$扩展到shell的进程ID,但显然您是对的,在本例中,
$
的计算结果是父shell的进程ID。感谢您的评论,我发现了shell变量BASHPID,手册上说:扩展到当前bash进程的进程id。在某些情况下,这与$$不同,例如不需要重新初始化bash的子shell。实际上,
echo$BASHPID
显示了不同的值。