4 ms·
It's kinda nonsense that `man set` doesn't provide that information. But it's kinda nonsense that those flags aren't the default, anyway.
by ajkjk 5y ago
It's kinda nonsense that `man set` doesn't provide that information. But it's kinda nonsense that those flags aren't the default, anyway.
- aidenn0 5y ago"man set" can't provide that information trivially without knowing your shell; dash/bash/ksh/zsh will all be subtly different. However, if you are running bash, "help set" is fine. FWIW, I really don't like pipefail as a default (e.g. piping to "head" causes random pipefails) and -e also has some confusing semantics. Also either failglob or nullglob are more important than either and -C is useful for some scripts as well. [edit] Simple example of confusing "set -e" semantics: The following does not print "hi" and shows returns error status, as expected: (set -e; echo hi); echo $? But put it in an if statement, and it's suddenly success, and does print hi: if (set -e; false; echo hi); then echo hello; fi The same problem applies to functions. The below function will remove all files in the current directory if it's called from a conditional, but not otherwise! foo() { set -e cd /some_directory # set -e means we exit if this fails rm -rf * } I think just defining a die() function and using it after any command that must succeed is more verbose, but less error prone: cd /some_directory || die "chdir failed" rm -rf *
- drran 5y ago> (set -e; echo hi); echo $? It works in my shell. :-/ It looks like you forgot to insert `false` command. You are pointing to the problem with -e not working in subshell/deep functions, because of POSIX. Right? It's described in bash documentation: http://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html http://www.gnu.org/software/bash/manual/html_node/The-Set-Bu... > I think just defining a die() function and using it after any command that must succeed is more verbose, but less error prone: Yep. It's the style I developed 12 years ago, when working at Bazaarvoice, when I was lead of devops team. I created the whole library for bash, to use this pattern consistently. See https://github.com/vlisivka/bash-modules#error-handling https://github.com/vlisivka/bash-modules#error-handling
- ebeip90 5y agoIf you're using ZSH, this will give you a Python-style backtrace showing the specific line of each failure, even with nested function calls. https://gist.github.com/zachriggle/8574964d2e3078cdfae84b5744a9d4dc https://gist.github.com/zachriggle/8574964d2e3078cdfae84b574... e.g. An error occurred on ./test:18 Frame 1 (./test:21) 18 false 19 } 20 21 >>> a Frame 2 (./test:6) 3 source TRAPERR.zsh 4 5 a() { 6 >>> b 7 } 8 9 b() { Frame 3 (./test:10) 7 } 8 9 b() { 10 >>> c 11 } 12 13 c() { Frame 4 (./test:14) 11 } 12 13 c() { 14 >>> d 15 } 16 17 d() { Frame 5 (./test:18) 15 } 16 17 d() { 18 >>> false 19 } 20 21 a
- drran 5y agoI can do this in bash too (partially), with `set -eE` and bash-modules: #!/bin/bash . import.sh strict log a() { b } b() { c } c() { d } d() { false } a Result: $ ./test.sh [test.sh] PANIC: Uncaught error. at d(./test.sh:13) at c(./test.sh:10) at b(./test.sh:7) at a(./test.sh:4) at main(./test.sh:16) However, it stops to work at some point, e.g. in `for` loop, or in a subshell. zsh is better in this regard.