外殼選項設置set
內建在子 shell 中繼承(至少是errexit
)。這可以透過以下方式證明:
set -o errexit
function foo() {
echo "foo:$BASHPID"
false
echo 'after'
}
echo "main:$BASHPID"
( foo )
然而,這些選項似乎沒有繼承命令替換,根據 Bash 文檔,它也應該是子 shell。證明:
set -o errexit
function foo() {
echo "foo:$BASHPID"
false
echo 'after'
}
echo "main:$BASHPID"
output=$(foo)
echo "output: $output"
預期輸出:
main:123
output: foo:124
實際輸出:
main:123
output: foo:124
after
這是預期的還是錯誤?
答案1
是的,這是預期的,當不處於 POSIX 模式時(例如執行 as 時sh
),basherrexit
預設會重設內部命令替換。
如果您想errexit
在 bash 4.4 或更高版本中保留命令替換,請使用:
inherit_errexit
如果設置,命令替換將繼承該選項的值
errexit
,而不是在子 shell 環境中取消設定。啟用 POSIX 模式時會啟用此選項。
啟用 POSIX 模式具有設定該選項的效果,因此產生的用於執行命令替換的子 shell 會從父 shell
inherit_errexit
繼承該選項的值。-e
當該inherit_errexit
選項未啟用時,Bash 會清除-e
此類子 shell 中的該選項。
核實:
$ bash -o errexit -c 'echo "$(echo "$SHELLOPTS")"'
braceexpand:hashall:interactive-comments
$ bash -o errexit -O inherit_errexit -c 'echo "$(echo "$SHELLOPTS")"'
braceexpand:errexit:hashall:interactive-comments
在 bash 4.2 及更早版本中,errexit
顯示在前者中,但仍有效停用:
$ bash-4.2 -o errexit c 'echo "$(false; echo "$SHELLOPTS")"'
braceexpand:errexit:hashall:interactive-comments
$ bash-4.2 -o posix -o errexit -c 'echo "<$(false; echo "$SHELLOPTS")> $?"'
<> 1