Bash 带代码块和管道的外壳出口代码

Bash 带代码块和管道的外壳出口代码,bash,shell,scripting,exit-code,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无效,脚本以exit code 0结束。(我想这是tee命令的退出

在一个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
无效,脚本以exit code 0结束。(我想这是tee命令的退出代码)

我试图在脚本末尾添加一行
exit$ERRL
,但它显示变量$ERRL在花括号外为空


我能做什么,在代码块出错时用错误代码结束脚本,而不丢失日志文件的输出?

这是因为退出代码是管道中最后一个命令之一,除非在管道之前设置了
set-o pipefail
。作为,包含管道中每个命令的退出代码,顺序与原始管道相同。

重定向整个脚本输出的最小干扰方式是在不涉及任何阻塞构造的情况下提前执行一次:

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

检查bash管道状态数组。参见Boo,hiss re:linking to the ABS(链接到ABS)——它因只是偶尔维护而臭名昭著,而且在没有完全不准确的情况下,还展示了不良行为。诚然,该特定页面并没有那么糟糕(有点过时,但没有明显的错误),但是回顾之前的页面,第9.2节完全缺少了一些bash 4.3更新,并且显示了一种非常容易出错的方法,在可靠的变量类型可用时识别变量类型。我为我的脚本选择PIPESTATUS解决方案,因为我只需要添加一行。但是下次我写类似的东西时,我会选择exec解决方案。