【问题标题】:Piping command output to tee but also save exit code of command [duplicate]管道命令输出到 tee 但也保存命令的退出代码 [重复]
【发布时间】: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 的返回码,但仍将输出通过管道传输到日志文件?

【问题讨论】:

    标签: bash shell pipe sh tee


    【解决方案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吗?
    • 当然。并且您可能想要创建一个临时文件以避免竞争条件。但是,正如您所看到的,还有更好的解决方案......
    猜你喜欢
    • 2012-02-08
    • 2021-05-20
    • 1970-01-01
    • 1970-01-01
    • 2021-04-05
    • 1970-01-01
    • 2018-08-18
    • 2019-11-08
    • 2017-06-02
    相关资源
    最近更新 更多