pipefail and Reliable Pipeline Failure Detection
Without `pipefail`, a successful final stage can hide a failed producer. Enabling it makes pipeline status more truthful, but production scripts still need to interpret expected statuses and understand SIGPIPE behavior.
Learning objectives
By the end of this lesson
- Explain default pipeline status.
- Enable and interpret pipefail.
- Capture PIPESTATUS.
- Recognize early-consumer SIGPIPE behavior.
- Preserve failure through tee and command substitution.
1. Normal pipeline status hides many upstream failures
false | true
printf 'status=%d\n' "$?"Without pipefail, the status of a pipeline is normally the status of its final command. A later success can hide an earlier failure.
2. pipefail changes the pipeline result
set -o pipefail
false | true
printf 'status=%d\n' "$?"With pipefail, the pipeline is non-zero when any stage fails. Bash reports the status of the rightmost failing command.
3. PIPESTATUS exposes every stage status
set +e
set -o pipefail
bash -c 'exit 3' |
bash -c 'exit 7' |
bash -c 'exit 0'
statuses=("${PIPESTATUS[@]}")
printf 'stage statuses: %s\n' "${statuses[*]}"Capture PIPESTATUS immediately. Running another command changes the array.
4. Not every non-zero stage means an infrastructure failure
set -o pipefail
if generate_data | grep -q '^READY$'; then
printf 'ready\n'
else
status=$?
printf 'pipeline did not succeed status=%d\n' "$status" >&2
figrep status 1 means “no match,” which may be an expected business result. Pipefail exposes the failure but does not interpret it for you.
5. Early-closing consumers can cause SIGPIPE upstream
set -o pipefail
yes data | head -n 1A consumer such as head may exit after reading enough data, causing an upstream producer to receive SIGPIPE. Under pipefail this can make the pipeline non-zero even though the visible output looks correct.
6. tee does not erase upstream failure under pipefail
set -o pipefail
if build_artifact 2>&1 | tee build.log; then
printf 'build succeeded\n'
else
status=$?
printf 'build failed status=%d\n' "$status" >&2
fiThis is a common reason to enable pipefail in CI scripts that need both logs and correct failure propagation.
7. Pipelines still have process-boundary behavior
Pipefail changes status propagation, not shell-state propagation. Pipeline stages may still run in separate processes, so variable updates inside them can disappear.
8. Capture pipeline output without discarding status
set -o pipefail
if output=$(generate_inventory | normalize_inventory); then
printf '%s\n' "$output"
else
status=$?
printf 'inventory pipeline failed=%d\n' "$status" >&2
exit "$status"
fiTest the command substitution itself so the combined pipeline status becomes explicit.
9. pipefail and errexit interact
set -e
set -o pipefail
producer | transformer | consumer
printf 'only reached if the pipeline succeeds\n'With both enabled, an unhandled pipeline failure may terminate the shell. The same grammar-context caveats from errexit still apply.
10. Sometimes a temporary file is easier to reason about
When you need per-stage diagnostics, retries, multiple consumers, or forensic evidence, a linear sequence with checked temporary artifacts can be clearer than one long pipeline.
11. Hands-on lab: reliable CI pipeline status
mkdir -p "$HOME/devops-academy/bash/chapter11/lesson03"
cd "$HOME/devops-academy/bash/chapter11/lesson03"
set -o pipefail
generate() {
printf '%s\n' INFO READY ERROR
return 0
}
if generate |
grep -v '^INFO$' |
tee filtered.log |
grep -q '^READY$'; then
printf 'gate=PASS\n'
else
status=$?
printf 'gate=FAIL status=%d\n' "$status" >&2
fi
printf '%s\n' '--- filtered log ---'
cat filtered.logVerification checklist
12. Knowledge check
Question 1. What status does a normal pipeline report by default?
Question 2. What does pipefail change?
Question 3. What does PIPESTATUS contain?
Question 4. Why can head create a surprising pipefail result?
13. Summary
pipefail prevents later success from hiding earlier pipeline failure, but it does not understand domain semantics. Interpret expected statuses explicitly, capture PIPESTATUS immediately when needed, and watch for early-closing consumers that intentionally cause SIGPIPE.
14. Further reading
- GNU Bash Reference Manual — Pipelines and
pipefail. - GNU Bash Reference Manual —
PIPESTATUS. - Linux
pipe(7)and signal documentation. - ShellCheck documentation — pipeline status handling.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this address.