This post appeared originally in our sysadvent series and has been moved here following the discontinuation of the sysadvent microsite

All in all, very odd, bash continues to be the most bizarre of languages, convoluted, twisted, but with strange solutions thrown in just when you are about to give up hope entirely.” (forum post at Techpatterns )

When re-working a database backup script at one of my customers I stumbled onto the problem that I wanted to have both proper error handling and at the same time avoid filling the disk.

The code providing the challenge was this

$MYSQLDUMP $MYSQLDUMP_OPTS $DB | gzip -9 > $BACKUP_FILE

I need to pipe the output of mysqldump to gzip instead of dumping to an intermediate file that then would be compressed, because otherwise I would fill the disk.

Normally I do error handling in scripts by evaluating $?, but to have proper error handling in here I need to capture the exit value of both mysqldump and gzip. And $? only gives me the exit value of gzip - the least important of the two.

Luckily, and not surprising, I’m not the first person to run into this problem, and by way of googling I found that Bash actually have a built-in way of giving me both exit values - the array $PIPESTATUS. $PIPESTATUS is an array with all the exit values from your last command line. $PIPESTATUS[0] contains the first exit value, $PIPESTATUS[1] the second and so on

sigurdur@ifconfig:~$ true | false
sigurdur@ifconfig:~$ echo ${PIPESTATUS[0]}
0
sigurdur@ifconfig:~$ true | false
sigurdur@ifconfig:~$ echo ${PIPESTATUS[1]}
1

You can also get the entire array

sigurdur@ifconfig:~$ true | false |false |true
sigurdur@ifconfig:~$ echo ${PIPESTATUS[@]}
0 1 1 0

A single, non-piped command is considered to be a “pipe of one”, thus leaving you with a $PIPESTATUS array with one value. Since $PIPESTATUS is updated after every command line I had to copy the array before extracting the exit values. So my code ended up like this:

$MYSQLDUMP $MYSQLDUMP_OPTS $DB | gzip -9
# We want the exit values of both mysqldump and gzip
exitarray=("${PIPESTATUS[@]}")
mydumpexitcode=${exitarray[0]}
gzipexitcode=${exitarray[1]}

PIPESTATUS have probably been part of Bash since forever, but to me it was new - and it solved my problem. Fun stuff:-)

Sigurd Urdahl

Senior Systems Consultant at Redpill Linpro

Sigurd has been working at Redpill Linpro longer than most of us can remember. He has seen countless computer systems stumble into trouble, and this has given him ample opportunity to hone his skills on finding faults and getting things back on track.

Comparison of different compression tools

Working with various compressed files on a daily basis, I found I didn’t actually know how the different tools performed compared to each other. I know different compression will best fit different types of data, but I wanted to compare using a large generic file.

The setup

The file I chose was a 4194304000 byte (4.0 GB) Ubuntu installation disk image.

The machine tasked with doing of the bit-mashing was an Ubuntu with a AMD Ryzen 9 5900X 12-Core ... [continue reading]

Why TCP keepalive may be important

Published on December 17, 2024

The irony of insecure security software

Published on December 09, 2024