简体   繁体   English

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

[英]Why trap didn't work in a pipeline

In this script We have a script trap.sh 在这个脚本中我们有一个脚本trap.sh

#!/bin/bash
trap "echo trapped" EXIT
exit 0

and test.sh. 和test.sh. If test.sh is like 如果test.sh是这样的

#!/bin/bash
. trap.sh

or 要么

#!/bin/bash
./trap.sh | :

trap works 陷阱工作

But if test.sh is like 但是如果test.sh是这样的话

#!/bin/bash
. trap.sh | :

the trap didn't work. 陷阱不起作用。

Anybody know why is this? 谁知道为什么会这样?

Better change your test command to . trap.sh|cat 更好地将测试命令更改为. trap.sh|cat . trap.sh|cat (standard output from trap.sh couldn't be displayed with : ). . trap.sh|cat (从标准输出trap.sh无法与显示: )。 But even then there is no output, so you are right: the trap didn't work. 但即便如此也没有输出,所以你是对的:陷阱不起作用。 This must be a bug in bash, and should be reported to the maintainers. 这必须是bash中的错误,应该向维护者报告。

Interestingly, when we echo $$ from inside the script trap.sh, we see that it is executed by the same shell that executes the whole pipeline . trap.sh|cat 有趣的是,当我们从脚本trap.sh内部echo $$时,我们看到它由执行整个管道的同一个shell执行. trap.sh|cat . trap.sh|cat , contradictory to the manual's statement: Each command in a pipeline is executed as a separate process (ie, in a subshell). . trap.sh|cat ,与手册的语句相矛盾: 管道中的每个命令都作为一个单独的进程执行(即,在子shell中)。 This was a fallacy, see comments. 这是一个谬论,请参阅评论。 Perhaps this is related to some optimization to minimize subshell creation, but that's just speculation. 也许这与最小化子shell创建的一些优化有关,但这只是推测。

I modified trap.sh to include the xtrace option. 我修改了trap.sh以包含xtrace选项。

#!/bin/bash
set -x
trap 'echo trapped' EXIT
exit 0

Running trap.sh as a script produces 运行trap.sh作为脚本生成

~ $ ./trap.sh | 〜$ ./trap.sh | cat + trap 'echo trapped' EXIT + exit 0 + echo trapped trapped 猫+陷阱'回声被困'出口+退出0 +被困陷阱被困

Sourcing it first, however produces 然而,首先采购它

~ $ . trap.sh | cat
++ trap 'echo trapped' EXIT
++ exit 0

This indicates that the trap is executed in a deeper subshell (why, I don't know), and that the trap itself is never executed (I confirmed in a second experiment by touch ing a file int he trap instead of just echoing, in case there was an issue with standard output being inherited; the file was never touched). 这表明trap是在更深的子shell中执行的(为什么,我不知道),并且陷阱本身永远不会被执行(我在第二个实验中通过touch陷阱中的文件而不是仅仅回显来确认有一个问题,标准输出被继承;文件从未被触及)。

My guess is that somehow the EXIT signal is being ignored prior to the source command being executed, based on this sentence from the description of the trap command in the man page: 我的猜测是,在执行source命令之前,以某种方式忽略EXIT信号,基于手册页中trap命令描述中的这句话:

Signals ignored upon entry to the shell cannot be trapped or reset. 进入shell时忽略的信号不能被捕获或重置。

As a result, the trap command is executed, but the trap itself is never registered, and so does not fire. 因此,执行trap命令,但陷阱本身从未注册,因此不会触发。

The command on the left hand side of a pipe is run in a subshell: 管道左侧的命令在子shell中运行:

exit | grep

The exit sigtrap seems not to be propagated to subshells. 退出sigtrap似乎不会传播到子shell。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM