Ich dachte, es set -e
hätte den gleichen Effekt auf Subshells wie auf Top-Level-Shell. Anscheinend nicht. Diese:
(
set -e
false
true
) || echo false1
bash -ec '
set -e
false
true
' || echo false2
bash <<EOF || echo false3
set -e
false
true
EOF
bash <<EOF || echo false4
false
true
EOF
bash <<EOF || echo false5
false &&
true
EOF
Druckt
false2
false3
false5
Wo ist das dokumentiert? Kann ich Subshells dazu bringen, bei Fehlern zu beenden, ohne alle ihre Befehle mit &&
(oder ohne || exit $?
nach jedem Befehl) zu verbinden?
Bearbeiten:
Mein besonderer Anwendungsfall war so etwas wie:
set -e
# ...
status=0
( false; true ) || status=$?
report_code $status
return $status
Wo der Inhalt der Subshell mein eigentlicher Code war. Das Problem dabei ist, dass der Status immer auf 0 gesetzt wird und das Ersetzen ||
durch ;
einen unerwünschten Fehlerausgang aufgrund der äußeren Menge -e verursacht.
Ich habe es gelöst mit:
set -e
# ...
set +e
( false; true ); status=$?
set -e
report_code $status
return $status
Ich wünschte, ich müsste das nicht tun, aber es scheint, dass alle gängigen Shells diese Dichotomie zwischen ausgeführter Subshell und nur gegabelter Subshell zeigen:
#!/bin/sh
echo FORK\'D:
export SH
for SH in dash bash ksh zsh; do
$SH -c 'st=0; ( set -e; false; true ) || st=$?; printf "%s\t%s\n" $SH $st; '
done
echo EXEC\'D:
for SH in dash bash ksh zsh; do
$SH -c 'st=0; '$SH' -c " set -e; false; true " || st=$?; printf "%s\t%s\n" $SH $st; '
done
AUSGABE:
FORK'D:
dash 0
bash 0
ksh 0
zsh 0
EXEC'D:
dash 1
bash 1
ksh 1
zsh 1
-e
Dokumentationsteil des Sets zu lesen .Antworten:
Beobachten:
Ebenfalls:
Offenbar , wenn der Unterschale durch eine folgt
||
,set -e
verursacht nicht die Subshell Ausfahrt auf das Erreichenfalse
Befehl. Stattdessen wird die Unterschale fortgesetzt und ausgeführttrue
(undecho inside=$?
).Die Philosophie von
set -e
ist typischerweise, dass es nur bei nicht erfassten Fehlern existiert. Hier||
scheint das Vorhandensein von außerhalb der Unterschale der Shell zu sagen, dass der Fehler innerhalb der Unterschale "abgefangen" wird und daherset -e
keinen Ausgang nachher verursachtfalse
.set -e
hat viele überraschende Verhaltensweisen. Siehe "Warum macht set -e nicht das, was ich erwartet habe?"Dokumentation
Das obige Verhalten wird in der Dokumentation unter
man bash
:quelle
set -e
nicht wirksam wäre.( set -e; false ; true ) || echo false1
. Die Subshell wird mit dem Rückkehrcode des letzten Befehlslaufs beendet. Da||
der Exit danach unterdrückt wirdfalse
, ist der letzte in der Subshell ausgeführte Befehltrue
. Somitfalse1
ist nicht , weil die Subshell Ausfahrten mit dem Rückkehrcode Null gedruckt.