Wie kann ich bedingt etwas tun, wenn ein Befehl erfolgreich war oder fehlgeschlagen ist?

Wie kann ich so etwas in bash tun?

if "`command` returns any error"; then echo "Returned an error" else echo "Proceed..." fi 

Antwort

Wie man etwas bedingt macht, wenn ein Befehl erfolgreich war oder fehlgeschlagen ist

Genau das ist Bash „s if Anweisung führt Folgendes aus:

if command ; then echo "Command succeeded" else echo "Command failed" fi 

Hinzufügen von Informationen aus Kommentaren: Sie don“ t muss in diesem Fall die Syntax [] verwenden. [ ist selbst ein Befehl, der fast test entspricht. Dies ist wahrscheinlich der häufigste Befehl in einem if, der dazu führen kann unter der Annahme, dass es Teil der Syntax der Shell ist. Wenn Sie jedoch testen möchten, ob ein Befehl erfolgreich war oder nicht, verwenden Sie den Befehl selbst direkt mit if, wie oben gezeigt.

Kommentare

  • Beachten Sie, dass das Semikolon wichtig ist.
  • Oder Sie können then in eine separate Zeile setzen.
  • @Joe: Ich denke du meinst if ! command ; then ... ; fi. [ ist selbst ein Befehl und ‚ wird in diesem Fall nicht benötigt.
  • @Joe: Mein Weg hat auch die Tugend, richtig zu sein. if [ ! command ] ‚ führt command nicht aus; Es behandelt command als Zeichenfolge und behandelt es als wahr, da es eine Länge ungleich Null hat. [ ist ein Synonym für den Befehl test
  • Ups. Sie ‚ sind korrekt.

Antwort

Für kleine Dinge Wenn ein Shell-Befehl funktioniert, können Sie das Konstrukt && verwenden:

rm -rf somedir && trace_output "Removed the directory" 

Ähnlich für Kleine Dinge, die passieren sollen, wenn ein Shell-Befehl fehlschlägt, können Sie ||:

rm -rf somedir || exit_on_error "Failed to remove the directory" 

oder beides verwenden

rm -rf somedir && trace_output "Removed the directory" || exit_on_error "Failed to remove the directory" 

Es ist wahrscheinlich unklug, sehr viel mit diesen Konstrukten zu tun, aber sie können gelegentlich den Kontrollfluss viel klarer machen.

Kommentare

  • Sie sind kürzer und (zumindest in einigen Shells) schneller. Ich schaudere, wenn ich mich an ein Monster-Ultrix-Installationsskript erinnere, das mit genau diesen bedingten Konstruktionen geschrieben wurde, die ich einmal versucht habe entschlüsseln …

Antwort

Überprüfen Sie den Wert von $?, das das Ergebnis der Ausführung des letzten Befehls / der letzten Funktion enthält:

#!/bin/bash echo "this will work" RESULT=$? if [ $RESULT -eq 0 ]; then echo success else echo failed fi if [ $RESULT == 0 ]; then echo success 2 else echo failed 2 fi 

Kommentare

  • Obwohl technisch korrekt (und daher keine Ablehnung erforderlich), ist es ‚ verwendet Bash nicht ‚ s if. Ich bevorzuge die Antwort von Keith Thompson ‚.
  • Diese Redewendung hat Vorteile – sie behält den Rückgabewert bei. Insgesamt finde ich diesen mächtiger, wenn auch ausführlicher. ‚ ist auch einfacher zu lesen.
  • Was ist “ Bash ‚ s if idiom „?
  • @Nowaker Die Tatsache, dass der einzige Zweck von if darin besteht, dies zu tun Dies. Die Flusskontrollbedingungen in Bash untersuchen alle $? hinter den Kulissen. Das ‚ ist das, was sie tun. Eine explizite Prüfung seines Wertes sollte in den allermeisten Fällen nicht erforderlich sein und ist normalerweise ein Anfänger-Antimuster.
  • Ich bevorzuge dies aus Gründen der Lesbarkeit. Der Hauptbefehl ist normalerweise sehr lang. Das Einfügen in eine “ if “ -Anweisung führt zu einer schlechten Lesbarkeit.

Antwort

Dies hat bei mir funktioniert:

command && echo "OK" || echo "NOK" 

wenn command ist erfolgreich, dann wird echo "OK" ausgeführt, und da dies erfolgreich ist, wird die Ausführung dort gestoppt. Andernfalls wird && übersprungen und echo "NOK" wird ausgeführt.

Kommentare

  • Wenn Sie etwas tun möchten, wenn es fehlschlägt, und beibehalten Mit dem Exit-Code (zum Anzeigen in der Eingabeaufforderung oder zum Testen in einem Skript) können Sie Folgendes tun: command && echo "OK" || c=$?; echo "NOK"; $(exit $c)
  • @ Sam-Hasler: sollte nicht ‚ t das ist command && echo "OK" || (c=$?; echo "NOK"; (exit $c))?
  • Auch wenn der echo "OK" Teil selbst sein könnte scheitern, dann ist dies besser: command && (echo "OK"; exit 0) || (c=$?; echo "NOK"; (exit $c))
  • @ jrw32982, Schön, ich ‚ habe die frühere Konstruktion verwendet, aber nicht letzteres.
  • Die wirkliche Antwort ist in den Kommentaren, danke an alle!

Antwort

Es ist zu beachten, dass if...then...fi und && / || Ansatz behandelt den Exit-Status, der von dem Befehl zurückgegeben wird, den wir testen möchten (0 bei Erfolg); Einige Befehle geben jedoch keinen Exit-Status ungleich Null zurück, wenn der Befehl fehlgeschlagen ist oder die Eingabe nicht verarbeiten konnte. Dies bedeutet, dass die üblichen Ansätze if und && / || für diese nicht funktionieren bestimmte Befehle.

Beispielsweise wird unter Linux GNU file immer noch mit 0 beendet, wenn eine nicht vorhandene Datei als Argument empfangen wurde und find konnte die vom Benutzer angegebene Datei nicht finden.

$ find . -name "not_existing_file" $ echo $? 0 $ file ./not_existing_file ./not_existing_file: cannot open `./not_existing_file" (No such file or directory) $ echo $? 0 

In solchen Fällen können wir die Situation möglicherweise durch Lesen von stderr / stdin Nachrichten, z diejenigen, die mit dem Befehl file zurückgegeben oder die Ausgabe des Befehls wie in find analysiert wurden. Zu diesem Zweck kann die Anweisung case verwendet werden.

$ file ./doesntexist | while IFS= read -r output; do > case "$output" in > *"No such file or directory"*) printf "%s\n" "This will show up if failed";; > *) printf "%s\n" "This will show up if succeeded" ;; > esac > done This will show up if failed $ find . -name "doesn"texist" | if ! read IFS= out; then echo "File not found"; fi File not found 

Antwort

Die Fehleranfälligkeit, die ich finden konnte, war:

  • Ermitteln Sie zuerst den Wert. Angenommen, Sie tun Folgendes:

RR=$?

Nun, nicht nur für diese Situation, sondern auch für andere, denen Sie möglicherweise gegenüberstehen: Betrachten Sie:

definierte Variable:

$ AA=1 ; if (( "10#0${AA}" == 1 )) ; then echo yes ; else echo no ; fi

Antwort: ja

$ AA=1 ; if (( "10#0${AA}" != 1 )) ; then echo yes ; else echo no ; fi

Antwort: nein

undefinierte Variable:

$ AA=1 ; if (( "10#0${BB}" == 1 )) ; then echo yes ; else echo no ; fi

Antwort: nein

$ AA=1 ; if (( "10#0${BB}" != 1 )) ; then echo yes ; else echo no ; fi

Antwort: ja

$ AA=1 ; if (( "10#0${BB}" == 0 )) ; then echo yes ; else echo no ; fi

Antwort: ja

Dies verhindert alle Arten von Fehlern.

Sie kennen wahrscheinlich die gesamte Syntax, aber hier einige Tipps:

  • Verwenden Sie Anführungszeichen. Vermeiden Sie, dass eine "blank" nothing ist.
  • Die neue moderne Notation für Variablen lautet .
  • Wenn Sie eine vor Ihrer Nummer verkettete Null hinzufügen, vermeiden Sie auch „überhaupt keine Nummer“.
  • Warten Sie, wenn Sie eine Null hinzufügen, wird die Nummer zu base-8. Sie erhalten eine Fehlermeldung wie:
    • value too great for base (error token is "08") für Zahlen über 7. Dann kommt 10# ins Spiel:
    • 10# erzwingt, dass die Zahl .

Antwort

Sie können dies tun:

if ($( ping 4.4.4.4 -c1 > /dev/null )) ; then echo "ping response succsess!!!" fi 

Kommentare

  • Das funktioniert, ist aber kompliziert. Wenn Sie ‚ Ping in einer Unterschale einer Unterschale ausführen, wird die Ausgabe von ping erfasst, um sie als Befehl auszuführen. Da die Ausgabe jedoch nach / dev / null umgeleitet wird, ist dies immer die leere Zeichenfolge. Sie ‚ führen also nichts in einer Subshell aus, was bedeutet, dass der vorherige Exit-Status (der Befehlsersetzungs-Subshell, dh Ping) beibehalten wird. Offensichtlich ist der richtige Weg hier if ping ...; then.

Antwort

Wie an anderer Stelle in diesem Thread erwähnt, beantwortet sich die ursprüngliche Frage im Wesentlichen von selbst. Hier ist eine Abbildung, die zeigt, dass if -Bedingungen auch verschachtelt sein können.

In diesem Beispiel wird if verwendet, um zu überprüfen, ob eine Datei vorhanden ist und ob es sich um eine reguläre Datei handelt. Wenn diese Bedingungen erfüllt sind, prüfen Sie, ob die Größe größer als 0 ist.

#!/bin/bash echo "Which error log are you checking today? " read answer if [ -f /opt/logs/$answer*.errors ] then if [ -s /opt/logs/$answer*.errors ] then echo "Content is present in the $answer error log file." else echo "No errors are present in the $answer error log file." fi else echo "$answer does not have an error log at this time." fi 

Kommentare

  • Das ist es, was Ihre Antwort tut, aber Ihre Antwort geht nicht auf die Frage ein.
  • @JeffSchaller, vielen Dank für Ihre Notiz. Ich habe meinen Beitrag so bearbeitet, dass er einen Verweis auf die Frage enthält.

Antwort

#!/bin/bash if command-1 ; then echo "command-1 succeeded and now running from this block command-2" command-2 else echo "command-1 failed and now running from this block command-3" command-3 fi 

Kommentare

Antwort

Dies kann einfach auf diese Weise erfolgen, da $? Ihnen den Status gibt des zuletzt ausgeführten Befehls.

Es könnte also

#!/bin/sh ... some command ... if [ $? == 0 ] ; then echo "<the output message you want to display>" else echo "<failure message>" fi 

Kommentare

    Downvote: Dies umschreibt einfach eine frühere Antwort, die zu Recht kritisiert wurde, weil sie unidiomatisch ist.

  • Eigentlich war dies genau das, wonach ich gesucht habe, weil ich es ‚ versuche Damit der Befehl “ “ das Skript als Teil von “ set -e “ was es nicht tut ‚ t wenn es ‚ Teil des if ist.Dies sollte nicht ‚ herabgestuft werden.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.