Home > Software design >  How to keep return value while processing a command's output?
How to keep return value while processing a command's output?

Time:09-16

In Bash environment, I have a command, and I want to detect if it fails.

However it is not failing gracefully:

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

When it runs without errors (successful run), it returns with 0. When it runs into an error, it can either

  • return with 1, easily detectable
  • return with 0, but during run it prints some error messages

I want to use this program in a script with these goals:

  • I need the output to be printing to stdout normally (not at once after it finished!)
  • I need to catch the output's return value by $? or similar
  • I need to grep for "error" string in the output and set a variable in case of presence

Then I can evaluate by checking the return value and the "error" output.

However, if I add tee, it will ruin the return value.

I have tried $PIPESTATUS[0] and $PIPESTATUS[1], but it doesn't seem to work:

program | tee >(grep -i error)

Even if there is no error, $PIPESTATUS[1] always returns 0 (true), because the tee command was successful.

So what is the way to do this in bash?

CodePudding user response:

#!/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

Tested as follows:

$ 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
  • Related