if else condition in shell script

if else condition in shell script

Stell dir vor, es ist Freitagabend, 22 Uhr. Ein automatisches Backup-Skript soll die Datenbanken der letzten Woche archivieren und auf einen Remote-Server schieben. Der Entwickler hat eine einfache Abfrage eingebaut, um zu prüfen, ob der Speicherplatz ausreicht. Er dachte, er beherrscht die if else condition in shell script und hat ein schnelles if [ $space > 100 ] hingeschrieben. Was er übersah: In der Bash ist > ein Umleitungsoperator, kein mathematischer Vergleich für Zahlen innerhalb einfacher eckiger Klammern. Das Skript hat nicht den Speicherplatz geprüft, sondern eine leere Datei namens "100" im Root-Verzeichnis erstellt und den Rest des Skripts einfach ausgeführt, obwohl die Platte zu 99 Prozent voll war. Das Ergebnis? Das Backup schlug fehl, das Dateisystem lief über, der Webserver quittierte den Dienst und drei Leute aus dem Team verbrachten ihr Wochenende damit, korrupte Tabellen zu reparieren. Ich habe solche Szenarien oft erlebt, bei denen kleine syntaktische Nachlässigkeiten Schäden im fünfstelligen Bereich verursacht haben, nur weil jemand die Feinheiten der Shell-Logik unterschätzt hat.

Die Falle der eckigen Klammern und warum Leerzeichen dein Budget fressen

Der häufigste Fehler, den ich in über zehn Jahren Shell-Scripting gesehen habe, ist die Ignoranz gegenüber der Tatsache, dass [ eigentlich ein Programm namens test ist. Viele Anfänger behandeln die Klammern wie in C oder Java. Sie schreiben if[$a==$b]. Das wird krachend scheitern. Die Shell erwartet Leerzeichen nach der öffnenden und vor der schließenden Klammer, weil sie jedes Element als separates Argument an das Test-Kommando übergibt. Ohne diese Leerzeichen erkennt das System den Befehl nicht.

Ein falsches Leerzeichen oder eine fehlende Anführungszeichen-Setzung führt dazu, dass Variablen, die leer sind, das ganze Skript sprengen. Wenn $VAR leer ist, wird aus if [ $VAR = "true" ] plötzlich if [ = "true" ]. Das wirft einen Syntaxfehler aus. In einem produktiven Deployment-Prozess bedeutet das: Die Pipeline bricht ab, die Entwickler warten, die Zeit läuft. Ich rate jedem: Setz Variablen immer in doppelte Anführungszeichen. Immer. Es gibt keinen Grund, es nicht zu tun, außer man will riskieren, dass eine leere Zeichenfolge das Skript terminiert.

Profi-Logik mit der if else condition in shell script richtig umsetzen

Wenn du wirklich Kontrolle über deine Abläufe haben willst, musst du den Unterschied zwischen [ und [[ kennen. Die doppelten Klammern sind ein Schlüsselmerkmal moderner Shells wie Bash oder Zsh. Sie sind mächtiger, sicherer und verhalten sich eher so, wie ein Programmierer es erwartet.

Hier ist ein Punkt, den viele übersehen: Innerhalb von [[ ]] musst du dir keine Sorgen um Wortaufspaltung oder Globbing machen. Du kannst Logik wie && und || direkt verwenden, anstatt dich mit den veralteten Parametern -a und -o von test herumzuschlagen. Wer heute noch die alten Single-Brackets für komplexe Logik nutzt, baut sich wissentlich technische Schulden auf, die später mühsam durch Debugging-Sitzungen abbezahlt werden müssen. Ich habe Projekte gesehen, bei denen hunderte Zeilen Code umgeschrieben werden mussten, nur weil das Team nicht von Anfang an auf die robustere Variante gesetzt hat.

Das Chaos der Rückgabewerte und die falsche Annahme von Wahrheit

In fast jeder anderen Sprache bedeutet 0 falsch und 1 wahr. In der Shell-Welt ist das genau umgekehrt. Ein Exit-Status von 0 bedeutet Erfolg (wahr), alles andere ist ein Fehler. Das führt zu absurden Fehlern, wenn Leute versuchen, Funktionen aus anderen Sprachen zu kopieren.

Ich erinnere mich an einen Fall, in dem ein Skript prüfen sollte, ob ein Nutzer existiert. Der Programmierer schrieb eine Funktion, die 1 zurückgab, wenn der Nutzer gefunden wurde. Die if-Abfrage wertete das als Fehler. Der Nutzer wurde also jedes Mal neu angelegt, was zu tausenden Dubletten in der Datenbank führte. In der Shell prüft der Prozess nicht den Wahrheitswert eines Ausdrucks im mathematischen Sinne, sondern den Rückgabewert eines Kommandos. Das ist ein fundamentaler Unterschied. Wenn du das nicht verinnerlichst, wirst du immer wieder Skripte schreiben, die genau das Gegenteil von dem tun, was du beabsichtigst.

Fehlerbehandlung statt blindem Vertrauen in Pfade

Ein massiver Reibungspunkt in der Praxis ist das Vertrauen darauf, dass Dateien dort sind, wo man sie vermutet. Ein klassisches Skript sieht oft so aus: „Wenn die Datei da ist, lösche das Verzeichnis.“ Früher hat man das so gemacht: if [ -f /tmp/lock ]; then rm -rf /data/prod; fi. Was passiert, wenn der Pfad zu /tmp/lock durch einen Tippfehler falsch ist? Das Skript macht einfach nichts oder löscht im schlimmsten Fall Daten, weil die Bedingung falsch evaluiert wurde.

Ein erfahrener Praktiker prüft nicht nur auf die Existenz, sondern auf Lesbarkeit, Schreibrechte und ob es sich überhaupt um eine Datei handelt. In einer realen Serverumgebung ändern sich Berechtigungen durch automatisierte Updates oder menschliche Fehler. Ein Skript, das diese Eventualitäten nicht abfängt, ist eine tickende Zeitbombe. Ich habe erlebt, wie ein Backup-Skript über Monate hinweg „erfolgreich“ lief, aber nur leere Archive erzeugte, weil die Bedingung zur Prüfung der Dateigröße falsch implementiert war. Niemand hat es gemerkt, bis der Ernstfall eintrat und keine Daten zur Wiederherstellung da waren.

Vorher: Der naive Ansatz

Ein Entwickler schreibt ein Skript, um alte Logs zu verschieben. Er nutzt if [ $count > 5 ]. Da er einfache Klammern verwendet, wird > als Umleitung interpretiert. Es wird eine Datei namens 5 erstellt. Die Bedingung ist für die Shell immer „wahr“, da das Kommando zum Erstellen der Datei erfolgreich war. Das Skript verschiebt also jedes Mal alle Logs, auch wenn erst ein einziger Eintrag vorhanden ist. Die Performance der Anwendung bricht ein, weil ständig unnötige I/O-Operationen auf dem langsamen Archivspeicher ausgeführt werden.

Nachher: Der sichere Weg

Nachdem der Fehler bemerkt wurde, wird das Skript auf if [[ $count -gt 5 ]] umgestellt. Die doppelten Klammern signalisieren der Bash, dass eine interne Evaluation stattfindet. Das -gt stellt sicher, dass ein numerischer Vergleich durchgeführt wird. Zusätzlich wird geprüft, ob $count überhaupt eine Zahl ist. Das Skript läuft jetzt nur noch dann, wenn es wirklich nötig ist. Die Serverlast sinkt sofort und die Protokolle bleiben so lange lokal verfügbar, wie sie für die Analyse gebraucht werden. Dieser kleine Wechsel spart Rechenleistung und sorgt für eine saubere Log-Struktur.

Warum "Exit on Error" dein bester Freund und dein größter Feind ist

Viele raten dazu, set -e am Anfang jedes Skripts zu nutzen. Die Idee: Das Skript bricht sofort ab, wenn ein Kommando fehlschlägt. Das klingt sicher, ist aber in Verbindung mit komplexen Verzweigungen oft gefährlich. Wenn du eine if-Bedingung hast, die ein Kommando prüft, das fehlschlagen darf, kann set -e das gesamte Skript beenden, bevor die else-Abzweigung überhaupt erreicht wird.

Es gibt keine Abkürzung für sauberes Error-Handling. Du musst jedes kritische Kommando einzeln prüfen. Wer denkt, er könne sich mit einem globalen Flag retten, wird spätestens dann eines Besseren belehrt, wenn ein Skript mitten in einer Transaktion abbricht und das System in einem undefinierten Zustand hinterlässt. In meiner Praxis habe ich gelernt, dass explizite Prüfungen nach jedem wichtigen Schritt zwar mehr Schreibarbeit bedeuten, aber die einzige Methode sind, um wirklich vorhersagbare Ergebnisse zu erzielen.

String-Vergleiche und die Tücken der lokalen Spracheinstellungen

Ein oft ignorierter Aspekt bei der if else condition in shell script ist die Umgebungsvariable LC_ALL oder LANG. Ich habe gesehen, wie Skripte auf einem deutschen Server perfekt funktionierten, aber auf einem US-Server komplett versagten. Warum? Weil die Sortierung von Zeichenfolgen oder die Interpretation von regulären Ausdrücken je nach Locale variieren kann.

Wenn du Strings vergleichst, besonders mit Mustern wie [[ $var == [a-z]* ]], kann die Groß- und Kleinschreibung je nach Systemkonfiguration unterschiedlich gehandhabt werden. Ein professionelles Skript setzt seine Umgebung explizit am Anfang fest. Wenn man das versäumt, baut man eine Abhängigkeit von der Serverkonfiguration ein, die bei einer Migration in die Cloud oder auf einen anderen Host zu unvorhersehbaren Fehlern führt. Das kostet Zeit, weil die Ursache oft nicht im Code selbst, sondern in der Interaktion mit dem Betriebssystem liegt.

Realitätscheck

Am Ende des Tages ist Shell-Scripting keine "echte" Programmierung im Sinne von Software-Architektur – es ist Systemadministration durch Textdateien. Es gibt keine Sicherheitsnetze. Es gibt keinen Compiler, der dich vor logischen Fehlern warnt. Wenn du denkst, du kannst mal eben schnell ein Skript hinklatschen, das wichtige Produktionsdaten manipuliert, spielst du mit dem Feuer.

Erfolg in diesem Bereich kommt nicht durch das Auswendiglernen von Handbüchern, sondern durch eine gesunde Paranoia. Du musst davon ausgehen, dass jede Variable leer sein kann, jeder Pfad fehlen kann und jedes Kommando fehlschlagen wird. Wer diese Einstellung nicht verinnerlicht, wird immer wieder an der Syntax scheitern. Shell-Skripte verzeihen nichts. Entweder du bist präzise, oder du wirst früher oder später aufräumen müssen, was deine Fehler angerichtet haben. Es gibt keinen magischen Trick, der Erfahrung ersetzt. Fang klein an, teste jeden einzelnen Zweig deiner Logik manuell und vertraue niemals darauf, dass ein Skript "einfach so" funktioniert, nur weil es auf deinem Laptop einmal durchgelaufen ist. In der echten Welt, auf echten Servern, ist die Umgebung immer anders. Wer das ignoriert, zahlt am Ende den Preis in Form von Überstunden und Datenverlust.

TS

Thomas Schäfer

Thomas Schäfer verfolgt politische und soziale Debatten mit kritischem Blick und journalistischer Verantwortung.