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

时间:2015-01-14 16:07:04

标签: bash shell scripting exit-code

在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 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

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