Opções de shell definidas porset
construídas emsão herdados em sub-shells (pelo menos o errexit
). Isto pode ser provado por:
set -o errexit
function foo() {
echo "foo:$BASHPID"
false
echo 'after'
}
echo "main:$BASHPID"
( foo )
No entanto, as opções não parecem herdadas emsubstituição de comando, que também devem ser subshells de acordo com a documentação do Bash. Prova:
set -o errexit
function foo() {
echo "foo:$BASHPID"
false
echo 'after'
}
echo "main:$BASHPID"
output=$(foo)
echo "output: $output"
Resultado esperado:
main:123
output: foo:124
Saída real:
main:123
output: foo:124
after
Isso é esperado ou um bug?
Responder1
Sim, é esperado que, quando não estiver no modo POSIX (como ao executar as sh
), o bash redefina errexit
dentro das substituições de comando por padrão.
Se você deseja errexit
ser preservado nas substituições de comandos, com bash 4.4 ou mais recente, use:
inherit_errexit
Se definido, a substituição do comando herda o valor da
errexit
opção, em vez de desmarcá-la no ambiente subshell. Esta opção é habilitada quando o modo POSIX está habilitado.
(DeManual do Bash.)Outra parte da documentaçãotornou mais explícito:
A ativação do modo POSIX tem o efeito de definir a
inherit_errexit
opção, portanto, os subshells gerados para executar substituições de comando herdam o valor da-e
opção do shell pai.Quando ainherit_errexit
opção não está habilitada, o Bash desmarca a-e
opção nesses subshells.
Verificar:
$ 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
No bash 4.2 e anteriores, errexit
era exibido no primeiro, mas ainda efetivamente desativado:
$ 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