Bash -o pipefail can have pitfails^Wpitfalls

Using `-o pipefail` is generally a good idea. However it can contain some surprises. For example the following shell script:

#!/bin/bash
set -e
set -o pipefail

output="$(cat /etc/passwd)"
for i in $(seq 100000); do
    echo "$output" | grep -q "^root" || res=$?
    if [ -n "$res" ]; then
        echo "failed: $i $res"
        exit 1
    fi
done
echo "done"

Does fail at different points in the loop. Why? Because grep is greedy and will exit as soon as it found a pattern. If the echo in the pipe did not finish writing to the pipe it will get a SIGPIPE when it tries to write the remaining data.

A better pattern is:

   grep -q -E "^root" <<< "$output"

Note that “-o pipefail” is already a bashism so adding “<<<" (which is also a bashism) does not make things worse 🙂

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.


%d bloggers like this: