【问题标题】:shell exit code with code-block and pipe带有代码块和管道的 shell 退出代码
【发布时间】:2015-01-14 16:07:04
【问题描述】:

在一个 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 在大括号外为空。

当代码块中出现问题时,我该怎么做才能以错误代码结束脚本 - 而不会丢失日志文件的输出?

【问题讨论】:

  • 检查 bash PIPESTATUS 数组。见tldp.org/LDP/abs/html/internalvariables.html
  • 嘘,咝咝作响:链接到 ABS——它只是偶尔维护,而且在不完全不准确的情况下会展示不良做法,这是相当臭名昭著的。诚然,该特定页面还不错(有点过时,但没有明显的完全错误),但回顾之前的那些页面,第 9.2 节完全缺少一些 bash 4.3 更新,并显示 非常在有可靠变量类型可用时识别变量类型的方法很容易出错。

标签: bash shell scripting exit-code


【解决方案1】:

重定向整个脚本输出的干扰最小的方法是预先这样做一次,而不涉及任何阻塞构造:

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

【讨论】:

  • 我为我的脚本选择了 PIPESTATUS 解决方案,因为我只需要添加一行。但是下次我写类似的东西时,我会选择执行解决方案。
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-08
    • 1970-01-01
    • 1970-01-01
    • 2013-01-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多