Bash Logik Operatoren kombinieren?
Hallo,
ich habe das folgende Problem. Ich möchte in einem Bash Script einen Befehl ausführen und wenn dieser fehlschlägt eine Nachricht ausgeben und das Script beenden. Gedacht war das also so:
systemctl status service || echo "Fehler" && exit 1
Allerdings dieser Ausdruck das Programm in jedem Fall. Wenn ich Klammern verwende, wird zwar die Nachricht ausgegeben, das Script aber nicht beendet.
systemctl status service || (echo "Fehler" && exit 1)
Wie muss man denn hier vorgehen, damit das gewünschte Ergebnis erzielt wird?
4 Antworten
Warum beendet
(echo "Fehler" && exit 1)
dein Skript nicht?
Mit "(" und ")" startest Du eine neue Subshell und das "exit 1" beendet diese Subshell. Einfacher Test: Öffne eine Terminal und schreibe einmal
echo "Fehler" && exit 1
und einmal
(echo "Fehler" && exit 1)
in die Kommandozeile. Im ersten Fall beendet sich das aufrufende Programm und Dein Terminal geht zu. Im zweiten Fall siehst Du nur die Ausgabe "Fehler" aber Dein Terminalprogramm bleibt offen.
Ich würde das völlig anders machen:
errhandler()
{
echo "Fehler"
exit 1
}
systemctl status service || errhandler
Das mit Klammern halte ich schon für den richtigen Ansatz, aber lass die 1 hinter dem exit mal weg. Vielleicht läuft der Fehler ja auch auf einen anderen Exitstatus.
Wenn du wissen willst, was im Fehlerfall genau für ein Exitstatus ausgegeben wird, dann ersetze exit 1 einfach durch echo $?
Stimmt, da war was ...
Naja, dann bleibt immer noch der klassische Weg:
if ! systemctl status service; then
echo "Fehler"
exit 1
fi
Wobei ich die 1 hinter dem exit immer noch weglassen würde.
In meinen Skripten nutze ich die Nummern nach exit eher intensiv, da ich an der Nummer in Logfiles sofort erkennen, welcher Fehler aufgetreten ist (sofern sich für das jeweilige Skript aus Gründen des Umfangs ein aufwändiges Fehlerhandling auch lohnt).
Das Problem, dass du hier eine Subshell öffnest wurde ja bereits erwähnt. Deshalb hier eine Alternative, die funktioniert:
befehl || { echo "Fehler" && exit 1; }
Am ende des Scripts end angeben.
Das Exit beendet lediglich nur den Befehl nicht das Script.
Seit wann denn das? Wenn ich exit interaktiv eingebe, wird die Shell beendet, im Falle einer Konsole bedeutet dies, dass der User abgemeldet wird. In einer Schleife wird zum Abbruch eines Durchlaufs dagegen break verwendet. Exit beendet dagegen das ganze Skript.
Ein "end" gibt es tatsächlich nicht in der bash; ein exit ja
Mein Kommentar bezieht sich auch auf die Antwort von Renecap (leider ist das in gutefrage ein wenig unglücklich dargestellt). Weder beendet exit nur den Befehl, noch gibt es end in der bash.
Den "end" Befehl scheint es nicht zu geben
-bash: end: command not found
Das kann nicht gehen, denn die Klammern starten eine Subshell und daher wird nur diese dann mit "exit" beendet.