【发布时间】:2015-02-17 06:06:25
【问题描述】:
我正在尝试将来自 stdout 和 stderr 的所有内容记录到日志文件中,并且仍然保留控制台。为此,我只是将:|& tee -a log_file.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 中,消息“检测到非零退出代码!”不见了。知道为什么吗? 谢谢!
【问题讨论】:
-
ERR 陷阱针对“简单命令”触发,管道不是简单命令。它可能会触发整个管道的结果(我不确定),并且您可以通过设置
pipefail获得更接近您想要的结果。这是人们通常不建议使用set -e的原因之一,因为它有这样令人惊讶的细节。 -
谢谢!我添加了
set -o pipefail,它起作用了。但是,我不太明白为什么不推荐set -e。它还有其他警告吗?另外,请添加答案以接受它。 -
set -e与您的ERR陷阱有类似的警告。它不会在您期望的所有情况下触发。其中一些情况在您原本可以工作的代码之外。 -
只是澄清一下,在脚本 2 中,通过设置
pipefail,管道的返回码仍然是 0(因为 tee 返回 0),但它可以让我的ERR陷阱以防万一第一个命令失败。这是正确的吗? -
我刚刚添加了一条评论,说明为什么
pipefail对我的答案有效,但是是的,它设置返回到最后一个失败的命令的退出状态,而不是始终是最后一个命令的退出状态正在筹备中。
标签: linux bash pipe tee bash-trap