I want to write a bash function to test whether or not a mysqldump
command succeeded. What I've tried so far is to test whether the dump file is zero size or not, like this:
l_mysqldump= # set your custom mysqldump path here, like /Applications/MAMP/Library/bin/mysqldump
${l_mysqldump:-mysqldump} -u$l_db_user -p$l_db_pass -h $l_db_host $l_db_name > latest-dump.mssql
if [[ -s latest-dump.mssql ]]
then
echo "Success: not zero size."
else
echo "Error: zero size."
exit 1
fi
I decided to test this way, rather than to test the exit status of the mysqldump
command, because when the default mysql server is down, running a mysqldump
command gives this error:
mysqldump: Got error: 2002: Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2) when trying to connect
Even though it throws up this error, it still generates a 0 byte .mssql file. Also, the exit status is 0 no matter what. The script has to exit if the dump failed, and needs to communicate to the user that they need to either specify a different mysqldump
binary or to activate their server.
The above piece of code works fine. However, I don't want mysqldump
to generate an uncompressed dump file. I want to bzip it, like this:
${l_mysqldump:-mysqldump} -u$l_db_user -p$l_db_pass -h $l_db_host $l_db_name | bzip2 -c > latest-dump.mssql.bz2
The problem is, this breaks my [-s]
bash test, because the .bz2 file it generates is 14 bytes. So even though the uncompressed .mssql file is size zero, the equivalent archive is not size zero.
So what's the best way to solve this? I could just generate an uncompressed dump file, test it, then bzip it after. I suspect there is a much smarter way to do this however.
The real problem is that with a pipe, the default return status is the exit code of the last command (bzip2
). To quote man bash
:
The return status of a pipeline is the exit status of the last command, unless the pipefail option is enabled. If pipefail is enabled, the pipeline's return status is the value of the last (rightmost) command to exit with a non-zero status, or zero if all commands exit success‐ fully.
If you want to report failure if any command of the pipe failed, you have to set the pipefail
option. Assuming bash
, here is an example (I don't have mysql server running on localhost):
sylvain@daal:~$ set -o pipefail
sylvain@daal:~$ if mysqldump -u root -p db | bzip2 -c > latest-dump.mssql.bz2; then echo ok; else echo non ok; fi
Enter password:
mysqldump: Got error: 2002: Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2) when trying to connect
non ok
For your particular case, you will write something like:
set -o pipefail
if ${l_mysqldump:-mysqldump} -u$l_db_user -p$l_db_pass -h $l_db_host $l_db_name | bzip2 -c > latest-dump.mssql.bz2
then
...
fi
To be more precise, since you use shell redirection, it is the host shell that create the file. Before it even tried to run the command.