Linux Bash:Trap ERR在使用管道操作符时不起作用

Linux Bash:Trap ERR在使用管道操作符时不起作用,linux,bash,pipe,tee,bash-trap,Linux,Bash,Pipe,Tee,Bash Trap,我试图将stdout和stderr中的所有内容都记录到一个日志文件中,并且仍然保留控制台。为此,我只是在每个命令中添加了:|&tee-一个log\u文件.log。 但是,如果脚本执行过程中出现任何错误,我还希望运行自定义命令。为此,我在脚本开头添加了以下内容:trap“echo Non-zero exit code detected”ERR 问题是通过使用管道操作符,陷阱中的回声不再执行 脚本1,不带管道: $cat test.sh #!/bin/bash trap "echo Non-zer

我试图将stdout和stderr中的所有内容都记录到一个日志文件中,并且仍然保留控制台。为此,我只是在每个命令中添加了:
|&tee-一个log\u文件.log

但是,如果脚本执行过程中出现任何错误,我还希望运行自定义命令。为此,我在脚本开头添加了以下内容:
trap“echo Non-zero exit code detected”ERR

问题是通过使用管道操作符,陷阱中的回声不再执行

脚本1,不带管道:

$cat test.sh
#!/bin/bash

trap "echo Non-zero exit code detected!" ERR

function fail_please()
{
    echo "Returning non-zero exit code!"
    return 1
}

fail_please 
产出1:

$ ./test.sh 
Returning non-zero exit code!
Non-zero exit code detected!
脚本2,带管道:

$ cat test.sh
#!/bin/bash

trap "echo Non-zero exit code detected!" ERR

function fail_please()
{
    echo "Returning non-zero exit code!"
    return 1
}

fail_please |& tee log_file.log 
产出2:

$ ./test.sh
Returning non-zero exit code!
$ cat log_file.log 
Returning non-zero exit code!
在输出2中,缺少消息“检测到非零退出代码!”。知道为什么吗?
谢谢

为“简单命令”触发的陷阱管道不是简单命令

它可能会触发整个管道的结果(我不确定),通过设置
pipefail
,您可能可以获得更接近您想要的结果

(注意:这是人们不推荐使用
set-e
的原因之一,因为它有这样令人惊讶的细节。)

pipefail
起作用的原因是管道的返回状态通常是最后一个命令的返回,但如果启用了
pipefail
,它将成为最后一个失败命令的返回状态

管道的返回状态是最后一个命令的退出状态, 除非启用了pipefail选项。如果启用pipefail,则 管道的返回状态是最后一个(最右边)命令的值 以非零状态退出,如果所有命令退出成功,则为零- 完全


错误陷阱为“简单命令”触发管道不是简单命令。它可能会触发整个管道的结果(我不确定),通过设置
pipefail
,您可能可以获得更接近您想要的结果。这也是人们不推荐使用
set-e
的原因之一,因为它有这样令人惊讶的细节。谢谢!我添加了
set-o pipefail
,它成功了。然而,我不太明白为什么不建议使用
set-e
。它还有其他警告吗?另外,请添加一个答案以接受它。
set-e
对您的
ERR
陷阱有类似的警告。它不会在所有你可能期望的情况下开火。其中一些情况是您的其他工作代码之外的。为了澄清这一点,在脚本2中,通过设置
pipefail
,管道的返回代码仍然为0(因为tee返回0),但如果第一个命令失败,它将启用my
ERR
陷阱。这是正确的吗?我刚刚在回答中添加了一条注释,说明了为什么
pipefail
有效,但是是的,它将返回到最后一个失败命令的退出状态,而不是始终是管道中最后一个命令的退出状态。