4 ms·
Am I the only one that thinks setting -e is a huge footgun given that it only works in certain contexts? I'd much rather see explicit error handling.
by themk 3y ago
Am I the only one that thinks setting -e is a huge footgun given that it only works in certain contexts? I'd much rather see explicit error handling.
- chungy 3y agoGiven that it makes a script terminate for any unhandled errors, I don't think your goal contradicts with setting -e. Rather, it makes the script author explicitly handle errors or the script dies.
- fbdab103 3y agoHandle errors in bash? More power to you, but if my script cannot just fail in place, then it will be written in Python. Even with shellcheck, I do not trust myself to write more than a handful of lines in bash.
- chungy 3y ago> Handle errors in bash? The || operator does that pretty well.
- js2 3y agoThe biggest issue with "set -e" is that it's inconsistent. It doesn't always cause the shell to exit where you'd expect it to, and in some cases, it causes the shell to exit where you would NOT expect it to. This is the most surprising: set -e i=0 (( i++ )) # shell will exit here Still, I tend to use it because even though it doesn't handle every case, I'd still usually rather my scripts exit when a command fails.
- floodle 3y agoThis doesn't cause an exit for me on GNU bash (3.2.57)
- js2 3y agoI copy/pasted the example from the Google bash scripting guide because I was on mobile earlier, but I just confirmed that it exits immediately after the arithmetic operation with bash 5.1.12.
- js2 3y agoThe change was made with bash-4.1: This is a terse description of the new features added to bash-4.1 since the release of bash-4.0. [...] j. The [[ and (( commands are now subject to the setting of `set -e' and the ERR trap." https://git.savannah.gnu.org/cgit/bash.git/tree/NEWS#n1078 https://git.savannah.gnu.org/cgit/bash.git/tree/NEWS#n1078 Test program: $ cat foo.sh #!/bin/bash set -eux echo "$BASH_VERSION" i=0 (( i++ )) echo "?=$? i=$i" (( i++ )) echo "?=$? i=$i" Running with 3.2.57: $ /bin/bash foo.sh + echo '3.2.57(1)-release' 3.2.57(1)-release + i=0 + (( i++ )) + echo '?=1 i=1' ?=1 i=1 + (( i++ )) + echo '?=0 i=2' ?=0 i=2 Running with 5.1.16: $ /opt/homebrew/bin/bash foo.sh + echo '5.1.16(1)-release' 5.1.16(1)-release + i=0 + (( i++ )) So the arithmetic operation returns non-zero in both cases where it evaluates to 0, but only under bash >= 4.1 does it cause bash to terminate. The moral of the story is to be careful with arithmetic operations that might evaluate to zero, or use this: (( operation )) || true
- Calzifer 3y agoAnother variant which I overlooked to often is if you have a construct which returns an error but does not exit the script later move it in a function and now it does exit the script. set -e [[ 0 == 1 ]] && true echo Status: $? will print "Status: 1" but set -e func() { [[ 0 == 1 ]] && true } func echo Status: $? will print nothing but exit after func returns.
- js2 3y agoThere's quite a few situations where it does NOT exit when you'd expect it to. This is one of those. What you're seeing there is a variant of the "Short-Circuiting Considerations" discussed here: http://redsymbol.net/articles/unofficial-bash-strict-mode/ http://redsymbol.net/articles/unofficial-bash-strict-mode/ Basically, when you short circuit, it will not cause the script to exit. However, the short circuit still affects the return value of the function, or the script itself if it's the last line of the script. So your short circuit is causing the function to return non-zero, which then causes the script to exit.