'How to have bash inherit failures from stdin subshells
Given the following contrived code:
#!/usr/bin/env bash
set -Eeuo pipefail
shopt -s inherit_errexit
echo 'before'
mapfile -t tuples < <(exit 1)
# ^ what option do I need to enable so the error exit code from this is not ignored
echo 'after'
Which produces:
before
after
Is there a set or shopt option that can be turned on such that <(exit 1) will cause the caller to inherit the failure, and thus preventing after from being executed? Such as what inherit_errexit and pipefail do in other contexts.
Solution 1:[1]
In bash 4.4 or later, process substitutions will set $!, which means you can wait on that process to get its exit status.
#!/usr/bin/env bash
set -Eeuo pipefail
shopt -s inherit_errexit
echo 'before'
mapfile -t tuples < <(exit 1)
wait $!
echo 'after'
mapfile itself (in general) won't have a non-zero status, because it's perfectly happy read what, if anything, the process substitution produces.
Solution 2:[2]
You can assign a variable with the output of the command. The variable assignment propagates errors from the command substitution.
t=$(exit 1)
echo 'after'
mapfile -t tuples <<<"$t"
Solution 3:[3]
If you have Bash 4.2 or later, since you are already setting errexit and pipefail, you can avoid the problem by using:
...
shopt -s lastpipe
exit 1 | mapfile -t tuples
shopt -s lastpipe causes the last command in a pipeline to be run in the current shell. See how does shopt -s lastpipe affect bash script behavior?. In this case it means that a tuples value read by mapfile can be accessed later in the code.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | chepner |
| Solution 2 | Barmar |
| Solution 3 | pjh |
