Let’s start by looking at the code of the shell:
ls whatever if [ $? -eq 0 ]; then echo "success" else echo "fail" fi
Since there is no file named ‘whatever’ in the current directory, the return code ‘$?’ will be none-zero and the program will finally print:
$ sh test.sh ls: whatever: No such file or directory fail
What will happen when someone wants to get the detail of the failed command in the shell script? Like, write error log into a file and also to the standard output, by using command ‘tee’?
ls whatever|tee log if [ $? -eq 0 ]; then echo "success" else echo "fail" fi
Unfortunately, the ‘$?’ will get the return status of ‘tee log’ instead of ‘ls whatever’. Then the snippet will print what we (at least myself) don’t expect:
ls: whatever: No such file or directory success
The reason is explained on this page.
We can modify our shell script by following the new method:
ls whatever|tee log if [ ${PIPESTATUS[0]} -eq 0 ]; then echo "success" else echo "fail" fi
Shame to say, even as a long term UNIX developer, this is the first time I know that the pipe symbol ‘|’ will also change the return status of the whole line of command.
There you can also use `set -o pipefail` to let the exit code of a pipeline be the first non-zero code as per the bash document at http://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#The-Set-Builtin .
Also, it’s the first time I know `PIPESTATUS`.
Very good suggestion. Thanks!