Warum übergibt Bash die Option „errexit“ nicht an Befehlsersetzungen?

Warum übergibt Bash die Option „errexit“ nicht an Befehlsersetzungen?

Shell-Optionen festgelegt durchseteingebautwerden in Unterschalen vererbt (zumindest in errexit). Dies kann wie folgt bewiesen werden:

set -o errexit

function foo() {
    echo "foo:$BASHPID"
    false
    echo 'after' 
}

echo "main:$BASHPID"
( foo )

Allerdings scheinen die Optionen nicht übernommen zu sein inBefehlsersetzung, die laut Bash-Dokumentation ebenfalls Subshells sein sollten. Beweis:

set -o errexit

function foo() {
    echo "foo:$BASHPID"
    false
    echo 'after' 
}

echo "main:$BASHPID"
output=$(foo)
echo "output: $output"

Erwartete Ausgabe:

main:123
output: foo:124

Tatsächliche Ausgabe:

main:123
output: foo:124
after

Ist das zu erwarten oder ein Fehler?

Antwort1

shJa, es wird erwartet, dass Bash außerhalb des POSIX-Modus (z. B. bei der Ausführung als ) errexitstandardmäßig innerhalb von Befehlsersetzungen zurückgesetzt wird.

Wenn Sie errexitbei Befehlsersetzungen mit Bash 4.4 oder neuer beibehalten werden möchten, verwenden Sie:

inherit_errexit

Wenn gesetzt, übernimmt die Befehlsersetzung den Wert der errexitOption, anstatt ihn in der Subshell-Umgebung zu deaktivieren. Diese Option ist aktiviert, wenn der POSIX-Modus aktiviert ist.

(AusBash-Handbuch.)Ein weiterer Teil aus der Dokumentationhabe es deutlicher gemacht:

Das Aktivieren des POSIX-Modus hat zur Folge, dass die inherit_errexitOption festgelegt wird, sodass zum Ausführen von Befehlsersetzungen erstellte Subshells den Wert der -eOption von der übergeordneten Shell erben.Wenn die inherit_errexitOption nicht aktiviert ist, löscht Bash die -eOption in solchen Subshells.

Verifizieren:

$ 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

In Bash 4.2 und älter errexitwurde im ersteren angezeigt, aber immer noch effektiv deaktiviert:

$ 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

verwandte Informationen