Some programs don't behave nicely when used in a pipe on unix-like systems. For example, I was using pg_dump piped through gzip like so:
Broken script: error condition never occurs
export PGPASSWORD=secret pg_dump -h host -U user db | gzip - > backup.sql.gz if [ $? -ne 0 ]; then ### Never happens: gzip never fails! ### echo Backup failed. exit 1 fi
This uses the normal way of checking the exit status of the previous command ($?
), but it doesn't work. If the pg_dump fails for any reason, gzip doesn't return any error response. $? is set to 0, indicating success.
Fortunately, there's a better way. In bash, the PIPESTATUS
environment variable is an array with the return codes of all the commands executed in the last pipe. Checking for the overall return status and the status of pg_dump is now done like this:
Correct script: check the result of pg_dump separately
export PGPASSWORD=secret pg_dump -h host -U user db | gzip - > backup.sql.gz if [ $? -ne 0 -o ${PIPESTATUS[0]} -ne 0 ]; then echo Backup failed. exit 1 fi
Now I can be sure my automated database backups aren't going to fail silently.