Explanation for newbies:
-
Shell is the programming language that you use when you open a terminal on linux or mac os. Well, actually “shell” is a family of languages with many different implementations (bash, dash, ash, zsh, ksh, fish, …)
-
Writing programs in shell (called “shell scripts”) is a harrowing experience because the language is optimized for interactive use at a terminal, not writing extensive applications
-
The two lines in the meme change the shell’s behavior to be slightly less headache-inducing for the programmer:
set -euo pipefail
is the short form of the following three commands:set -e
: exit on the first command that fails, rather than plowing through ignoring all errorsset -u
: treat references to undefined variables as errorsset -o pipefail
: If a command piped into another command fails, treat that as an error
export LC_ALL=C
tells other programs to not do weird things depending on locale. For example, it forcesseq
to output numbers with a period as the decimal separator, even on systems where coma is the default decimal separator (russian, dutch, etc.).
-
The title text references “posix”, which is a document that standardizes, among other things, what features a shell must have. Posix does not require a shell to implement
pipefail
, so if you want your script to run on as many different platforms as possible, then you cannot use that feature.
The issue with
set -e
is that it’s hideously broken and inconsistent. Let me copy the examples from the wiki I linked.Or, “so you think set -e is OK, huh?”
Exercise 1: why doesn’t this example print anything?
#!/usr/bin/env bash set -e i=0 let i++ echo "i is $i"
Exercise 2: why does this one sometimes appear to work? In which versions of bash does it work, and in which versions does it fail?
#!/usr/bin/env bash set -e i=0 ((i++)) echo "i is $i"
Exercise 3: why aren’t these two scripts identical?
#!/usr/bin/env bash set -e test -d nosuchdir && echo no dir echo survived
#!/usr/bin/env bash set -e f() { test -d nosuchdir && echo no dir; } f echo survived
Exercise 4: why aren’t these two scripts identical?
set -e f() { test -d nosuchdir && echo no dir; } f echo survived
set -e f() { if test -d nosuchdir; then echo no dir; fi; } f echo survived
set -e
would absolutely be more elegant if it worked in a way that was easy to understand. I would be shouting its praises from my rooftop if it could make Bash into less of a pile of flaming plop. Instead, it’s a labyrinthian mess of fucked up hacks.Let me leave you with a parable copied directly from that same wiki page. It’s too long for me to post it in this comment, so I’ll respond to myself.
Exercise 6:
That one was fun to learn.
Even with all the jank and unreliability, I think
set -e
does still have some value as a last resort for preventing unfortunate accidents. As long as you don’t use it for implicit control flow, it usually (exercise 6 notwithstanding) does what it needs to do and fails early when some command unexpectedly returns an error.From https://mywiki.wooledge.org/BashFAQ/105
This is great and thanks for taking the time to enlighten us 😄