Ist es möglich, den Status des letzten Befehlsausgangs ( $?
) nach einem Test unverändert zu lassen?
ZB möchte ich machen:
command -p sudo ...
[ $? -ne 1 ] && exit $?
Der letzte exit $?
sollte den sudo-Exit-Status zurückgeben, gibt jedoch immer zurück 0
(den Exit-Code des Tests).
Ist das ohne temporäre Variable möglich?
Ein weiteres Beispiel zur weiteren Verdeutlichung:
spd-say "$@"
[ $? -ne 127 ] && exit $?
In diesem Fall möchte ich nur beenden, wenn der erste Befehl gefunden wird (Exit-Code! = 127
). Und ich möchte mit dem eigentlichen spd-say
Exit-Code beenden (möglicherweise nicht
0
).
EDIT: Ich habe vergessen zu erwähnen, dass ich eine POSIX-Beschwerdelösung für eine bessere Portabilität bevorzuge.
Ich verwende dieses Konstrukt in Skripten, in denen ich Alternativen für denselben Befehl bereitstellen möchte. Siehe zum Beispiel mein crc32-Skript .
Das Problem mit temporären Variablen besteht darin, dass sie andere Variablen beschatten können. Um zu vermeiden, dass Sie lange Namen verwenden müssen, ist dies für die Lesbarkeit des Codes nicht gut.
quelle
if ! command -p sudo; then exit; fi
was für Ihr Beispiel die gleichen Ergebnisse hätte.[ $? -ne 127 ] && exit $?
)sudo
Befehl erfolgreich ist (dh wenn ersudo
mit dem Status 0 beendet wird). Aber in Ihrem Code läuft das Skript weiter (wird nicht beendet), wennsudo
es erfolgreich istcommand
und überhaupt nicht basierensudo
. Das ist gemeint mit Ich möchte nur beenden, wenn der erste Befehl gefunden wird (Exit-Code! = 127) und ist eine angegebene Rückgabe,command
wenn der aufgerufene Befehl nicht gefunden wird. Ich denke, das Problem ist, dass das Aufrufensudo
als Teil des Tests es ermöglicht,sudo
die Rückkehr voncommand
an erster Stelle zu quetschen und so den Test zu verzerren .Antworten:
$_
arbeitet in wird (mindestens) interaktivdash
,bash
,zsh
,ksh
(wenn auch offensichtlich nicht in einer bedingten Anweisung wie gewünscht) undmksh
Muscheln. Von diesen - meines Wissens - nurbash
undzsh
wird es auch in einer Skript-Shell füllen. Es ist kein POSIX-Parameter - aber für jede moderne, interaktive Shell ziemlich portabel.Für eine tragbarere Lösung können Sie Folgendes tun:
Dies ermöglicht es Ihnen grundsätzlich, den Anfangswert für
$?
bis zum Ende des Skripts zu erweitern, bevor Sie den Wert überhaupt an der Spitze testen.Aber wie auch immer, da Sie scheinen zu testen , ob der Befehl
sudo
kann builtin in der Schale ist zu finden-p
tragbare Pfad mit einer Schnurcommand
, würde ich denken , dass Sie es ein litte mehr direkt gehen könnten. Auch nur klar zu sein,command
wird nicht für den Standort aller testen Argumente zusudo
- so ist es nur istsudo
- und nichts , um es ruft - die zu diesem Rückgabewert relevant ist.Und wenn Sie das versuchen:
... würde als Test gut funktionieren, ohne dass Fehler in den Befehlsläufen auftreten,
sudo
die so zurückgegeben werden, dass die Ergebnisse Ihres Tests verzerrt werden.quelle
Abhängig von den tatsächlichen Anforderungen gibt es verschiedene Optionen, um den Exit-Status zuverlässig und ohne Overhead zu handhaben.
Sie können den Exit-Status mithilfe einer Variablen speichern:
Sie können Erfolg oder Misserfolg direkt überprüfen:
Oder verwenden Sie ein
case
Konstrukt, um den Exit-Status zu unterscheiden:mit dem in der Frage gestellten Sonderfall:
Alle diese Optionen haben den Vorteil, dass sie dem POSIX-Standard entsprechen.
(Hinweis: Zur Veranschaulichung habe ich die
echo
obigen Befehle verwendet. Ersetzen Sie sie durch entsprechendeexit
Anweisungen, um der angeforderten Funktion zu entsprechen.)quelle
("$(get_errnos)")
ist eine künstliche Hinzufügung einer Befehlssubstitution, bei der Vergleiche mit tatsächlichen Fehlercodes in der Frage verlangt werden. 2.) In der Norm ist klar, was sich ändert$?
(und was sich nicht ändert), und 3.) dort sind keine Nebenwirkungen mit diesem Konstrukt (es sei denn, Sie führen sie unnötig ein). - OTOH, da es Ihnen etwas ausmacht, ist die andere Antwort, die Sie bevorzugen, eindeutig nicht standardisiert.$(get_errnos)
Code auf andere Lösungen anwenden würden (( exit 42 ); test "$(get_errnos)" -ne $? && echo $_
), funktionieren diese ebenfalls nicht. (Sie haben es vorgezogen, meine Standardlösung in Fehlkrediten zu bringen , nicht die anderen nicht standardmäßigen Hack (s) .) - Natürlich können Sie allen Antworten beliebigen Code hinzufügen und ihn verderben. - Und WRT zur Änderung von$?
; Nur weil du es nicht finden kannst, heißt das nicht, dass es nicht wahr ist. (Ich habe in unseren Diskussionen bereits die Schlüsselwörter angegeben, nach denen in POSIX gesucht werden soll.)zsh
(zuerst allein erwähnt; später haben Sie auch hinzugefügtdash
), dass ich denke, dass es dort ein Fehler sein muss, da dercase
Exit-Status und die Einstellung von$?
in POSIX gut definiert zu sein scheinen. - Und auch hier wenden Sie Doppelmoral an; Der andere Hack ist z. B. weder Standard noch funktioniert er zuverlässig in anderen Standard-Shells (zksh
. B. nicht in ). - Meine Vorschläge sind Standard und funktionieren inbash
(meistens unter Linux verwendet) undksh
(der vorherrschenden Shell in kommerziellen Unixen).Use
$_
, das bis zum letzten Argument des vorherigen Befehls erweitert wird.quelle
$?
und kein anderer Befehl befindet$_
. IMHO ist es besser, sich an eine konsistente Methode zu halten, die in anderen Fällen funktioniert (und auch die Lesbarkeit des Codes verbessern kann).case
Mustern , der einzige Ort, der theoretisch von Bedeutung wäre (aber nicht in der gegebenen Frage), ist ein konstruierter Fall. - In jedem Fall würde Ihre Shell-Befehlsersetzung das Ergebnis des eingebetteten Befehls weitergeben. In der Regel wirken sich andere Erweiterungen ohnehin nicht auf den Rückgabestatus aus, wenn keine Befehle beteiligt sind, die Fehler verursachen können (Mindx=${a!b}
Cases, aber hier irrelevant). - Was meinst du mit "Befehl ohne Befehlsname" ?Sie können eine Shell-Funktion definieren (und verwenden):
Dann
Dies ist wohl "Betrug", da es eine Kopie
$?
in dercheck_exit_status
Argumentliste erstellt.Dies mag etwas umständlich erscheinen, und das ist es auch. (Das passiert manchmal, wenn Sie Problemen willkürliche Einschränkungen auferlegen.) Dies mag unflexibel erscheinen, ist es aber nicht. Sie können
check_exit_status
komplexer gestalten, indem Sie Argumente hinzufügen, die angeben, welche Tests für den Exit-Statuswert durchzuführen sind.quelle
Um Ihre direkte Frage zu beantworten, nein, es ist nicht möglich,
$?
unverändert zu bleiben . Und dies ist einer der Fälle, in denen Sie sich vermutlich auf das falsche Problem konzentrieren. Eine temporäre Variable ist der Standard- und bevorzugte Weg, um den gewünschten Effekt zu erzielen. Es ist so normal, dass ich vorschlagen würde, den Grund aufzugeben (oder zu überdenken), von dem Sie glauben, dass Sie ihn nicht verwenden möchten. Ich bezweifle sehr, dass es die zusätzliche Komplexität wert ist, die durch jede andere Methode hinzugefügt wird.Wenn Sie nur aus einfacher Neugier fragen, lautet die Antwort nein.
quelle
$?
oder so etwas?Hier ist mein Code-Snippet, um einen vorherigen Exit-Status beizubehalten, ohne das aktuelle Skript / die aktuelle Shell zu verlassen
quelle