シェルオプションの設定set
組み込みサブシェルから継承されます(少なくともerrexit
)。これは次のように証明できます。
set -o errexit
function foo() {
echo "foo:$BASHPID"
false
echo 'after'
}
echo "main:$BASHPID"
( foo )
しかし、これらのオプションは継承されないようです。コマンドの置き換え、Bash文書によると、これはサブシェルでもあります。証明する:
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
はい、これは予想される結果です。 bashは、POSIXモードでない場合(たとえば、実行されている場合sh
)、errexit
デフォルトで内部コマンド置換をリセットします。
errexit
Bash 4.4以降でコマンドの置き換えを維持するには、次のようにします。
inherit_errexit
errexit
設定されている場合、コマンド置換はサブシェル環境で設定を解除するのではなく、このオプションの値を継承します。このオプションは、POSIXモードが有効な場合に有効になります。
(からバッシュマニュアル.)文書の他の部分より明確にするには:
inherit_errexit
POSIXモードを有効にすると、コマンドオーバーライドを実行するために作成されたサブシェルが親-e
シェルから継承されるようにこのオプションを設定する効果があります。inherit_errexit
Bashは、アクティブでない-e
サブシェルからこのオプションを消去します。
確認する:
$ 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