首页 文章

带有代码块和管道的shell退出代码

提问于
浏览
3

在shell脚本中,我使用带有大括号的代码块将所有输出传递给控制台,并将一个带有tee的日志文件传递给控制台 .

#!/bin/bash

{
  echo "Foo bar"
  echo "foo bar on STDERR" >&2
  ERRL=66
  exit 99
} 2>&1 | tee log-file.log

(这只是一个小的演示脚本,原来要复杂得多)

问题是,行 exit 99 没有效果,脚本以退出代码0结束 . (这是tee命令的退出代码,我认为)

我试图在脚本的末尾添加行 exit $ERRL ,但它显示,变量$ ERRL在大括号外是空的 .

我可以做什么,在代码块中出现问题时用错误代码结束脚本 - 而不会丢失输出到日志文件?

2 回答

  • 4

    重定向整个脚本输出的最少侵入性方法是一次性预先执行此操作,不涉及任何阻塞构造:

    exec > >(tee log-file.log) 2>&1 # redirect stdout and stderr to a pipe to tee
    
    echo "Foo bar"
    echo "foo bar on STDERR" >&2
    ERRL=66
    exit 99
    

    备用选项包括使用 pipefail 设置...

    set -o pipefail
    { ... } 2>&1 | tee log-file.log
    

    ......或者在事后明确地拉出退出状态:

    { ... } 2>&1 | tee log-file.log
    exit "${PIPESTATUS[0]}"
    

    ...或者只是使用不是管道的重定向:

    { ... } > >(tee log-file.log) 2>&1
    
  • 0

    这是因为退出代码是管道中最后一个命令之一,除非在管道之前有 set -o pipefail . 作为@jimmcnamara hinted$PIPESTATUS array包含管道中每个命令的退出代码,其顺序与原始管道相同 .

相关问题