我有一个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的错误输出始终为空(看起来它只写入stdout)。
如何保留mvn clean install
的返回码但仍将输出汇总到日志文件?
答案 0 :(得分:173)
您可以设置pipefail
shell option选项以获得所需的行为。
管道的退出状态是最后一个命令的退出状态 在管道中,除非启用
pipefail
选项(请参阅The Set Builtin)。 如果启用了pipefail
,则管道的返回状态为 以非零状态退出的最后(最右边)命令的值, 如果所有命令都成功退出,则为零。
示例:
$ false | tee /dev/null ; echo $?
0
$ set -o pipefail
$ false | tee /dev/null ; echo $?
1
恢复原始管道设置:
$ set +o pipefail
答案 1 :(得分:131)
由于您正在运行bash
,因此您可以使用其$PIPESTATUS变量而不是$?
:
mvn clean install $@ | tee $logfile
echo ${PIPESTATUS[0]}
答案 2 :(得分:11)
你可以运行mvn命令并缓存退出代码......我的例子使用“false”命令。
$ { false ; echo $? > /tmp/false.status ; } | tee $logfile
$ cat /tmp/false.status
1
通过这种方式,您可以使用状态文件内容做出进一步的决定。
我现在很好奇是否有更有说服力的方法来实现这一目标。
答案 3 :(得分:3)
解决方法(注意:perfer @ Frederic的解决方案):
f=`mktemp`
(mvn clean install $@; echo $?>$f) | tee $logfile
e=`cat $f` #error in variable e
rm $f