Linux – How to check the exit status of several piped commands
Article Number: 330 | Rating: Unrated | Last Updated: Wed, Jul 25, 2018 2:00 PM
As piping in bash commands is common and very usefull, controling the exit status of each piped commands in bash scripting can be vital, especially for backups.
I was checking by a customer the backups of a critical MySQL instance and was surprised even stunned that the return status of all of them was always successfull when tested but physically on disk, the dumps were all empty.
No valid backups since a long time meaning no possible recovery.
Oups! How can it be?
I immediately opened the backup script with “vi” and had a look to the used statement which was the following:
1
|
mysqldump -u $USERNAME -p $PASS $DBNAME | bzip2 -9c -c > Dump.sql.gz |
Now, what if the backup failed and the bzip2 command succeeded? In fact, the exit status will be the one of the last command.
1
2
|
echo $? 0 |
And this will be always successfull.
So, the solution to check the exit status of a particular command in piped commands is to use an inbuilt linux variable called PIPESTATUS.
PIPESTATUS is an array variable which contain the exit status of every piped commands.
In our case,
echo ${PIPESTATUS[0]} will refer to the backup and will be greater than 0 if it fails
echo ${PIPESTATUS[1]} will refer to the compression
echo ${PIPESTATUS[1]} will refer to the compression
echo ${PIPESTATUS[*]} or echo ${PIPESTATUS[@]} will give you the status of both.
So, one solution in our example could be:
1
2
3
4
5
6
7
8
|
mysqldump -u $USERNAME -p $PASS $DBNAME | bzip2 -9c -c > Dump.sql.gz if [ ${PIPESTATUS[0]} - ne "0" ] then echo "the MySQL Database backup failed with Error: ${PIPESTATUS[0]}" ; else echo "The MySQL Database backup was successfull!" ; fi |