Learning set -euo pipefail
I’ve been writing shell scripts since I started learning about computers and programming. This close to two decades by now. They started simple: scp
a file here, loop over a few filenames there.
Over time, the scripts grew some evolved into wrappers for pipelines, cron jobs, Docker entrypoints, or even local dev automation. I thought I knew what I was doing.
But recently, I stumbled (again) on something I’d seen many times but never fully respected:
set -euo pipefail
I’d copied it before without thinking. Assumed it was “safer” somehow. I never gave it more attention than a passing glance.
Now I actually know what it does. And it’s changed how I write scripts which I do now more than the number of meals I eat in a week.
So what does it do?
-e
: if any command fails (non-zero exit), the script exits.-u
: if you use an undefined variable, it crashes immediately.-o pipefail
: a pipeline fails if any command in it fails, not just the last one.
This combo enforces strict, predictable behavior. It prevents a large class of silent errors. For example:
grep "match" file.txt | head -n 1
If file.txt
doesn’t exist, grep
fails. But head
still exits 0. So your script looks successful even though it wasn’t. With pipefail
, that failure doesn’t get swallowed.
Since adopting it seriously, I’ve caught bad variable names, missing files, broken assumptions, and silently ignored errors before they caused downstream problems.
But it’s not all upside.
Once you enable this, you need to be deliberate:
If something is allowed to fail, you must guard it:
command_that_can_fail || true
If a variable might not be set, use defaults:
: "${MY_VAR:=default}"
And some legacy pipelines might need rewriting to survive under stricter rules.
So why bother?
- It’s better to fail early and loudly than to have something succeed for the wrong reasons.
- Debugging a broken script is much easier when it refuses to lie to you.
- Reliable automation depends on predictable failure modes (like this).
I wish I learned this when I first started scripting, but I was too lazy, so I didn’t. But I’m using it now. And now, I won’t write another serious script without it.