如何在处理命令输出时保持 return 值?

How to keep return value while processing a command's output?

在Bash环境下,我有一个命令,我想检测它是否失败。

然而它并没有优雅地失败:

# ./program
do stuff1
do stuff2
    error!
do stuff3
# echo $?
0

当它 运行 没有错误(成功 运行)时,它 return 会 0。当它 运行 出错时,它可以

我想在具有以下目标的脚本中使用此 program

然后我可以通过检查 return 值和“错误”输出来进行评估。

但是,如果我添加 tee,它会破坏 return 值。

我已经尝试了 $PIPESTATUS[0]$PIPESTATUS[1],但似乎没有用:

program | tee >(grep -i error)

即使没有错误,$PIPESTATUS[1]总是returns 0 (true),因为tee命令成功了。

那么在bash中有什么方法可以做到这一点呢?

#!/usr/bin/env bash
case $BASH_VERSION in
  ''|[0-3].*|4.[012].*) echo "ERROR: bash 4.3+ required" >2; exit 1;;
esac

exec {stdout_fd}>&1
if "$@" | tee "/dev/fd/$stdout_fd" | grep -i error >/dev/null; then
  echo "Errors occurred (detected on stdout)" >&2
elif (( ${PIPESTATUS[0]} )); then
  echo "Errors detected (via exit status)" >&2
else
  echo "No errors occurred" >&2
fi

测试如下:

$ myfunc() { echo "This is an ERROR"; return 0; }; export -f myfunc
$ ./test-err myfunc
This is an ERROR
Errors occurred (detected on stdout)
$ myfunc() { echo "Everything is not so fine"; return 1; }; export -f myfunc
$ ./test-err myfunc
Everything is not so fine
Errors detected (via exit status)
$ myfunc() { echo "Everything is fine"; }; export -f myfunc
$ ./test-err myfunc
Everything is fine
No errors occurred