我有一个shell脚本,其中包装了一个命令(mvn clean install),将输出重定向到一个日志文件。

#!/bin/bash
...
mvn clean install $@ | tee $logfile
echo $? # Does not show the return code of mvn clean install

现在,如果mvn清洁安装失败与一个错误,我希望我的包装壳脚本也失败与该错误。但是由于我将所有输出管道到tee,我不能访问mvn清洁安装的返回代码,所以当我访问$?之后,它总是0(因为tee成功)。

我尝试让命令将错误输出写入一个单独的文件,然后检查,但mvn的错误输出总是空的(似乎它只写到stdout)。

我如何保存mvn清洁安装的返回代码,但仍然管道输出到一个日志文件?


由于您正在运行bash,您可以使用它的$PIPESTATUS变量而不是$?:

mvn clean install $@ | tee $logfile
echo ${PIPESTATUS[0]}

您可以运行mvn命令并缓存退出代码…在我的例子中,我使用“false”命令。

$ { false ; echo $? > /tmp/false.status ; } | tee $logfile
$ cat /tmp/false.status
1

这样您就可以使用状态文件内容来做出进一步的决定。

我现在很好奇是否有一种更有力的方式来实现这一点。


解决方案(注:一个更好的@Frederic的解决方案):

f=`mktemp`
(mvn clean install $@; echo $?>$f) | tee $logfile
e=`cat $f` #error in variable e
rm $f

您可以设置pipefail shell选项选项以获得您想要的行为。

来自Bash参考手册:

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

例子:

$ false | tee /dev/null ; echo $?
0
$ set -o pipefail
$ false | tee /dev/null ; echo $?
1

恢复原来的管道设置:

$ set +o pipefail