管道命令输出到 tee 但也保存命令的退出代码 [重复]
Posted
技术标签:
【中文标题】管道命令输出到 tee 但也保存命令的退出代码 [重复]【英文标题】:Piping command output to tee but also save exit code of command [duplicate] 【发布时间】:2011-10-15 20:34:49 【问题描述】:我有一个 shell 脚本,我在其中包装了一个命令(mvn clean install),以将输出重定向到一个日志文件。
#!/bin/bash
...
mvn clean install $@ | tee $logfile
echo $? # Does not show the return code of mvn clean install
现在,如果 mvn clean install
因错误而失败,我希望我的包装器 shell 脚本也因该错误而失败。但由于我将所有输出通过管道传输到 tee,我无法访问 mvn clean install
的返回码,因此当我之后访问 $?
时,它始终为 0(因为 tee 成功)。
我尝试让命令将错误输出写入单独的文件并随后检查,但 mvn 的错误输出始终为空(似乎只写入标准输出)。
如何保留mvn clean install
的返回码,但仍将输出通过管道传输到日志文件?
【问题讨论】:
【参考方案1】:您可以设置pipefail
shell option 选项以获得您想要的行为。
来自Bash Reference Manual:
管道的退出状态是最后一条命令的退出状态 在管道中,除非启用了
pipefail
选项(请参阅The Set Builtin)。 如果启用pipefail
,则管道的返回状态为 以非零状态退出的最后一个(最右边)命令的值, 如果所有命令都成功退出,则为零。
例子:
$ false | tee /dev/null ; echo $?
0
$ set -o pipefail
$ false | tee /dev/null ; echo $?
1
恢复原始管道设置:
$ set +o pipefail
【讨论】:
这似乎是一个比公认的解决方案更优雅的解决方案 同意。接受的答案要求您提前知道管道中的哪个命令会失败。如果您将 5 个不同的命令连接在一起,您将不得不猜测数组中的哪一个会失败。 或者在 PIPESTATUS 上做一个循环 恢复原来的管道设置:$ set +o pipefail
注意,pipefail
在 ubuntu 上也被 dash
支持【参考方案2】:
由于您正在运行bash
,因此您可以使用它的$PIPESTATUS 变量而不是$?
:
mvn clean install $@ | tee $logfile
echo $PIPESTATUS[0]
【讨论】:
如下所述,如果您有多个管道,则需要检查每个命令的状态以了解失败的位置。 完美运行,谢谢。 也很重要:变量是短暂的,所以即使“回显”它也会让你失去运行管道的价值。将其分配给另一个变量,除非您将立即访问它,并且只访问一次。【参考方案3】:您可以运行 mvn 命令并缓存退出代码...我在示例中使用“false”命令。
$ false ; echo $? > /tmp/false.status ; | tee $logfile
$ cat /tmp/false.status
1
这样您就可以使用状态文件的内容来做出进一步的决定。
我现在很好奇是否有更雄辩的方法来实现这一点。
【讨论】:
我希望最终答案不是特定于 shell 的(即:仅限 bash)。 完美!我更喜欢这个不仅仅依赖 bash :-) 谢谢@Demosthenex 但我使用 ( ) 而不是 来捕获输出 ....【参考方案4】:解决方法(注意:一个 perfer @Frederic 的解决方案):
f=`mktemp`
(mvn clean install $@; echo $?>$f) | tee $logfile
e=`cat $f` #error in variable e
rm $f
【讨论】:
我们可以用read e < $f
而不是cat
保存一个fork吗?
当然。并且您可能想要创建一个临时文件以避免竞争条件。但是,正如您所看到的,还有更好的解决方案......以上是关于管道命令输出到 tee 但也保存命令的退出代码 [重复]的主要内容,如果未能解决你的问题,请参考以下文章