Betrachten Sie die Befehle
eval false || echo ok
echo also ok
Normalerweise würden wir erwarten , dass dies das auszuführen false
Dienstprogramm , und da der Exit - Status ungleich Null ist, dann ausführen echo ok
und echo also ok
.
In allen POSIX-wie Muscheln ich ( ksh93
, zsh
, bash
, dash
, OpenBSD ksh
, und yash
), das ist , was passiert, aber die Dinge interessant , wenn wir ermöglichen set -e
.
Wenn dies der set -e
Fall ist, beenden OpenBSDs sh
und ksh
Shells (beide abgeleitet von pdksh
) das Skript, wenn das ausgeführt wird eval
. Keine andere Shell macht das.
Laut POSIX sollte ein Fehler in einem speziellen integrierten Dienstprogramm (z. B. eval
) dazu führen, dass die nicht interaktive Shell beendet wird. Ich bin mir nicht ganz sicher, ob das Ausführen false
"einen Fehler" darstellt (wenn dies der Fall wäre, wäre es unabhängig davon set -e
, aktiv zu sein).
Der Weg, dies zu umgehen, scheint darin zu bestehen, das eval
in eine Sub-Shell zu setzen.
( eval false ) || echo ok
echo also ok
Die Frage ist, ob ich das in einem POSIX-korrekten Shell-Skript tun muss oder ob es ein Fehler in der OpenBSD-Shell ist. Was ist mit "Fehler" im oben verlinkten POSIX-Text gemeint?
Zusätzliche Informationen: Die OpenBSD-Shells führen echo ok
sowohl mit als auch ohne set -e
im Befehl aus
eval ! true || echo ok
Mein ursprünglicher Code sah aus wie
set -e
if eval "$string"; then
echo ok
else
echo not ok
fi
Dies würde bei Verwendung der OpenBSD-Shells nicht ausgegeben werden (es würde enden), und ich war mir nicht sicher, ob es beabsichtigt, versehentlich oder durch Missverständnisse oder etwas anderes war.not ok
string=false
eval false
generiert einen Status ungleich Null, sodass ich erwarten würdeset -e
, das Skript an diesem Punkt zu beenden. Im Falle von!
set -e
gilt nicht, da die!
Anweisung den Exit-Status explizit überprüft.eval false
, das Skript zu beenden, auch wenn es Teil einer UND-ODER-Liste oder einer bedingten Anweisung ist? Ich würde nicht.set -e
ist, ob dies das richtige Verhalten ist ... Ich stimme zu, dass es sinnvoll ist, nicht in einer bedingten Anweisung zu beenden.set -e
also ist das `()` die Antwort.Antworten:
Dass keine andere Shell eine solche Problemumgehung benötigt, ist ein starker Hinweis darauf, dass es sich um einen Fehler in OpenBSD ksh handelt. Tatsächlich zeigt ksh93 ein solches Problem nicht.
Dass sich
||
in der Befehlszeile ein befindet, muss den Shell-Exit vermeiden, der durch einen Rückkehrcode von 1 auf der linken Seite verursacht wird.Der Fehler einer speziellen integrierten Funktion führt zum Beenden einer nicht interaktiven Shell gemäß POSIX. Dies ist jedoch nicht immer der Fall. Der Versuch,
continue
aus einer Schleife herauszukommen, ist ein Fehler undcontinue
ein integrierter Fehler. Aber die meisten Muscheln gehen nicht aus:Ein eingebautes Gerät, das einen eindeutigen Fehler ausgibt, aber nicht beendet wird.
Der Exit on
false
wird also durch dieset -e
Bedingung generiert , nicht durch die eingebaute Charakteristik des Befehls (eval
in diesem Fall).Die genauen Bedingungen, unter denen beendet werden
set -e
soll, sind in POSIX ziemlich unscharf.quelle
[Entschuldigung, wenn dies keine echte Antwort ist, werde ich sie aktualisieren, wenn ich dazu komme]
Ich habe mir den Quellcode angesehen und meine Schlussfolgerungen sind:
1) Es ist ein Fehler / eine Einschränkung, nichts Philosophisches dahinter.
2) Das "Update" von der tragbaren Gabel von OpenBSDs ksh (
mksh
) ist sehr schlecht, was die Sache nur noch schlimmer macht, ohne es wirklich zu reparieren:Neuer Fehler, der sich von allen anderen Shells unterscheidet:
Immer noch nicht wirklich behoben:
Sie können ersetzen
bash
oben mitdash
,zsh
,yash
,ksh93
etc.quelle