带有代码块和管道的 shell 退出代码
Posted
技术标签:
【中文标题】带有代码块和管道的 shell 退出代码【英文标题】:shell exit code with code-block and pipe 【发布时间】: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 更新,并显示 非常在有可靠变量类型可用时识别变量类型的方法很容易出错。 【参考方案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 包含管道中每个命令的退出代码,其顺序与原始管道相同。
【讨论】:
以上是关于带有代码块和管道的 shell 退出代码的主要内容,如果未能解决你的问题,请参考以下文章