Suppose you have a following script sandbox.sh
.
(This looks similar to Command substitution inside a function does not stop the script on a failure even if -e is set, but I believe a bit different one)
At "The Line", I am trying to pass an output from func2
to func1
as a positional parameter.
#!/bin/bash
set -eu -o pipefail -E
shopt -s inherit_errexit
function func1() {
local arg="${1}"
echo "(func1)This line shouldn't be reached:arg='${arg}': '${?}'" >&2
}
function func2() {
echo "value from func2"
exit 1
}
var="$(func1 "$(func2)")" # The Line
echo "main:This line shouldn't be reached:var='${var}':'${?}'" >&2
This is a possible situation, where a programmer desires to construct a data by reusing existing functions in a concise manner, I believe.
However, this results in following output.
$ bash sandbox.sh
(func1)This line shouldn't be reached:arg='value from func2': '0'
main:This line shouldn't be reached:var='':'0'
$
I interpreted this behavior that the sub-shell that invokes func2
is not inheriting errexit
behaviour from the sub-shell for func1
.
Thus, func1
takes unset value as its argument.
I tried to make it work intendedly by modifying "The Line", like
# A.
var="$(set -e; func1 "$(set -e; func2)")" # The Line
Or
# B.
var="$(func1 "$(func2 || exit 1)" || exit 1)" # The Line
But no luck yet. Actually, I am puzzled at neither A. nor B. not fixing the behavior. What is a best practice for this? Or shouldn't I attempt to nest command substitutions from the first place?
echo "$(false)"
; functions are irrelevant to the general issue. This example also shows that nested command-replacement isn't necessary to experience the issue. – bukzor Feb 11 '21 at 23:40set -euo pipefail; shopt -s inherit_errexit
is a questionable thing. No good solution. Although some recommend it. No generally accepted opinion as well. As for the boilerplate code, that sounds like a bad practice. – x-yuri Oct 20 '21 at 14:29