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.