Sometimes you may need to capture an exit code of a command while keeping the errexit
option enabled during execution of that command.
|| rc=$?
or wrapping the command in an if
statement, does not work correctly for compound commands and functions as ||
, if
, while
, etc. will completely disable the errexit
option for that command, therefore failures in the middle of a function will not cause that function to fail.
Example:
set -euo pipefail
failing_fn () {
return 5
}
complex_fn () {
true
failing_fn
echo 'Should not see me'
}
rc=UNCHANGED
complex_fn || rc=$?
echo "$rc"
outputs
Should not see me
UNCHANGED
One could use the PIPESTATUS
trick, like complex_fn | cat; rc=${PIPESTATUS[0]}
but it does not work with -o pipefail
Here’s one of the ways to handle this:
set +e
(set -e; complex_fn)
rc=$?
set -e
echo "$rc"
outputs 5
This method also works with pipes and -o pipefail
:
set +e
(set -e; true | complex_fn | true)
rc=$?
set -e
echo "$rc"
also outputs 5