0

I have this:

my_test() {

    ltt -y
    echo "$? ........echo $LINENO @ `basename $0` done"
    date
    echo "$? ........echo $LINENO @ `basename $0` done"
}
export -f my_test

This fails as expected:

$ /bin/bash -c 'set -o pipefail -o errexit && my_test | ts "%FT%T"' #1

This doesn't

$ /bin/bash -c 'set -o pipefail -o errexit && my_test | ts "%FT%T" && date +%s' #2

Why so? I was hoping # 2 to fail

Output:

$ /bin/bash -c 'set -o pipefail -o errexit && my_test | ts "%FT%T"' #1
/bin/bash: ltt: command not found 

And

$ /bin/bash -c 'set -o pipefail -o errexit && my_test | ts "%FT%T" && date +%s' #2
/bin/bash: ltt: command not found
2018-03-28T22:37:45 127 ........echo 1 @ bash done
2018-03-28T22:37:45 Wed Mar 28 22:37:45 UTC 2018
2018-03-28T22:37:45 0 ........echo 3 @ bash done
1522276665 # this comes from date +%s
Ankur Agarwal
  • 23,692
  • 41
  • 137
  • 208
  • 1
    See [BashFAQ #105](http://mywiki.wooledge.org/BashFAQ/105) -- the exercises below, if you don't have the patience for the allegory up top. – Charles Duffy Mar 28 '18 at 22:46
  • 1
    Short form: This is normal, expected, documented behavior: Branching on the exit status of a function marks all code inside the function as "checked", and thus not subject to `set -e`. – Charles Duffy Mar 28 '18 at 22:48
  • 1
    (See also https://www.in-ulm.de/~mascheck/various/set-e/, tracking how different shells' implementations of `set -e` diverge. In sum, the behavior of `errexit` is highly variable, hard-to-predict, and thus both nonportable (frequently across releases of the same shell!) and often unintuitive; amongst old hands in bash, its usage is thus... contentious, to say the least). – Charles Duffy Mar 28 '18 at 22:50
  • (Also see discussion of `set -e` in http://wiki.bash-hackers.org/scripting/obsolete) – Charles Duffy Mar 28 '18 at 22:53
  • This was closed as duplicate too soon. If `set -e` does not work in functions then why is #1 working as expected above ? @CharlesDuffy – Ankur Agarwal Mar 28 '18 at 23:30
  • 2
    it doesn't work in functions **when the exit status of those functions is checked**. `some_function && anything` is doing a branch (to either invoke `anything` or not do so) based on the exit status of the function. Therefore, the function call is checked, therefore `set -e` does not apply; when you don't use `&&`, `or`, or put the function call in an `if`, it's unchecked. Please read the linked resources (and, for that matter, my comments -- the second one explained this distinction) closely. – Charles Duffy Mar 29 '18 at 15:07
  • 2
    Yes, this is unintuitive -- that's known. To quote from one of the links above, emphasis from the original: "**The `set -e` feature generates more questions and false bug reports on the Bash mailing list than all other features combined!** Please do not rely on `set -e` for logic in scripts. If you still refuse to take this advice, make sure you understand **exactly** how it works." – Charles Duffy Mar 29 '18 at 15:13

0 Answers0