Implement set -o pipefail
feat: I want set -o pipefail
. #272 (closed) asked for both errexit
and pipefail
, but so far only errexit
is implemented.
BREAKING CHANGE: it is possible to add pipefail
without breaking existing scripts by defaulting it to off. In the perfect world both errexit
and pipefail
would have been always on without any way to disable them (just like in all programming languages that have exceptions except for Visual Basic), but that might break existing scripts.
perf: impact
performance none
usability increase
maintainability increase
code: input
set -eo pipefail
echo 1
false | true
echo 2
expect: output
1
reason: I want my script to fail fast by default if an external command fails.
context:
Executing an external command can fail for a million different reasons. Here are some examples:
- The external command is not installed
- It encounters an internal bug and fails fast and loud
- It receives bad input due to a bug in my script
- An admin kills it
- The OOM Killer kills it https://linuxwheel.com/oom-killer-explained/
- It tries to talk to another process possibly on a different machine and that fails for any reason
- It uses a temporary file for internal buffering and /tmp is full
- It tries to read or write a file and that fails for any reason
A robust script can not afford to ignore the possibility that any of the external commands it executes may fail. Often the right choice of action is to fail fast because the code that follows requires that the preceding commands executed successfully.
Unix-y pipelines have an issue:
foo | bar
If foo
exits successfully bar
sees EOF. If foo
fails bar
also sees EOF. bar
has no way to know whether foo
failed or not. In many cases bar
will exit successfully even if foo
fails. The script has to detect that and fail. This is why you often see set -o errexit -o pipefail
in bash.
Unfortunately set -o errexit
is very broken in bash which is why I'm looking for a different shell.