Relentless Coding

A Developer’s Blog

Prevent Exit When Receiving SIGPIPE with Pipefail Set

When a program that is part of a pipeline quits, it closes its stdin and stdout. Programs that produce the input for the quitted process may still try to write to its stdin. Since they cannot, they will receive a SIGPIPE from the kernel.

You can see this in action:

$ seq 1 10000 | head -1
1
$ echo "${PIPESTATUS[@]}"
141 0

Conventionally, an exit status N greater than 128 indicates the program was terminated by signal N - 128. Since SIGPIPE is signal 13, 141 - 128 = 13 indicates your program was ended by a SIGPIPE.

Source

When running scripts with set -o pipefail, this will terminate the script, however. A workaround is to check for exit code 141 and exit the pipeline with 0 instead:

seq 1 10000 | head -1 || \
    { if [ "$(kill -l "$?")" = PIPE ]; then exit 0; else exit "$?"; fi; }