Pages

2011-01-07

Bash - How to check the exit status of pipe command


Piping in bash commands are common.
Checking exit status of a command in bash scripting is essential.
How about checking exit status of the commands in a pipe?





Example:

mysqldump -u $db_username -p $db_name | gzip -c > output.sql.gz

One would just check the exit status of the above using :
echo $?

But the exit status will always be "0" as that's the exit status of the last command, which is the "gzip -c > output.sql.gz".

In order to check the exit status of a particular command in the "pipe command", examine the bash special array, "PIPESTATUS". That's where bash store exit status of the recent command from a pipe.
E.g. :
  1. ${PIPESTATUS[0]} refers to the first command in the "pipe command"
  2. ${PIPESTATUS[1]} refers to the second command in the "pipe command"
  3. ${PIPESTATUS[2]} refers to the third command in the "pipe command"
and so on

Here's an example of how to check a program exit code in a pipe command :
#!/usr/local/bin/bash

db_username="myusername"
db_name="mydatabase"

mysqldump -u $db_username -p $db_name | gzip -c > ./output.sql.gz;

if [ ${PIPESTATUS[0]} -ne "0" ];
then
    echo "the command \"mysqldump\" failed with Error: ${PIPESTATUS[0]}";
    exit 1;
else
    echo "Database dump successfully!";
fi

Shalom !!!

ref : Bash manual - PIPESTATUS

2 comments:

  1. Thank you so much!
    I was scratching my head over the exit status of
    netstat -ntap | grep sshd
    in a bash script, to find if ssh service is running. And i would get exit status 0 evrytime even when ssh was down.

    ReplyDelete
  2. The $PIPESTATUS variable is a great tip :)

    There's a small bug with the example though, once you access PIPESTATUS it gets overwritten:

    $ false
    $ echo $PIPESTATUS[0]
    1[0]
    $ echo $PIPESTATUS[0]
    0[0]

    This essentially means you'll always get "failed with error 0" in the event of a failure.

    Do it like this:

    mysqldump -u $db_username -p $db_name | gzip -c > ./output.sql.gz;
    MYSQL_RET=${PIPESTATUS[0]}

    if [ ${MYSQL_RET} -ne "0" ];
    etc...

    ReplyDelete