How to detect errors in a bash pipe
Perhaps you have enabled the errexit option in your bash script, but you have noticed that it may not stop executing if it gets an error when executing a command that pipes into another command. This is because when commands are executing in a pipe the status of the last command is returned.
Lets demonstrate this on the bash command line using the builtin commands ‘true’ and ‘false’. If you are not familiar with these commands they are pretty simple. The command true will simply return a return code of 0 (success) and the ‘false’ command will return a return code of 1 (failure).
You can see this by issuing the following command and echoing the code.
❯ true
❯ echo $?
0❯ false
❯ echo $?
1
Now lets see what happens in the bash shell by default when the false command is piped to the true command.
❯ false | true
❯ echo $?
0
As you can see it returned 0, this is because in the pipe the last command to execute was ‘true’ so the pipe will return 0 which means success. Lets try it the other way.
❯ true | false
❯ echo $?
1
This time it returned 1 because false was last. The subtile behavior here is any of the commands in the pipe can fail but if the last command completes successfully the bash script can mask errors that are difficult to find.
There is a bash option called pipefail that when enabled will halt the command pipe at the first failure and return error or if all of the commands in the pipe suceed it will return success.
❯ set -o pipefail❯ false | true
❯ echo $?
1❯ true | false
❯ echo $?
1
As you can see now both scenarios will return error. To use this functionality in a script you probably want to also enable the errexit option too so that the script doesn’t have to check the error status of every command pipe. So your bash script will begin like the following.
#!/bin/bashset -o errexit # stop script immediately on error
set -o pipefail # enable strict command pipe error detection# Bash script functionality here #
To learn about the errexit option see this article. Today we learned that by default piped bash commands will return the status of the last command executed. This can cause bash scripts to suppress errors making them difficult to debug. To detect errors in a command pipe the script needs to enable the pipefail option, so that it will fail the pipe if any command fails. If you found the article useful let me know by giving me a clap.