如何在处理命令输出时保持 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
。当它 运行 出错时,它可以
- return 和
1
,容易检测
- return 与
0
,但在 运行 期间它会打印一些错误消息
我想在具有以下目标的脚本中使用此 program
:
- 我需要输出正常打印到标准输出(不是在完成后立即打印!)
- 我需要通过
$?
或类似的 来捕捉输出的 return 值
- 我需要
grep
输出中的“错误”字符串并设置一个变量以防出现
然后我可以通过检查 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
在Bash环境下,我有一个命令,我想检测它是否失败。
然而它并没有优雅地失败:
# ./program
do stuff1
do stuff2
error!
do stuff3
# echo $?
0
当它 运行 没有错误(成功 运行)时,它 return 会 0
。当它 运行 出错时,它可以
- return 和
1
,容易检测 - return 与
0
,但在 运行 期间它会打印一些错误消息
我想在具有以下目标的脚本中使用此 program
:
- 我需要输出正常打印到标准输出(不是在完成后立即打印!)
- 我需要通过
$?
或类似的 来捕捉输出的 return 值
- 我需要
grep
输出中的“错误”字符串并设置一个变量以防出现
然后我可以通过检查 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