for i in 1..10 bash

for i in 1..10 bash

Stell dir vor, es ist Freitagnachmittag, kurz vor vier. Ein Junior-Admin möchte schnell die Log-Dateien von zehn verschiedenen Servern archivieren. Er denkt sich nichts dabei und tippt For I In 1..10 Bash in sein Terminal, um eine kleine Schleife zu starten. Was er nicht ahnt: Einer der Server reagiert träge, die SSH-Verbindung bleibt hängen, und weil er keine Timeouts oder Fehlerbehandlung eingebaut hat, blockiert das gesamte Skript. Während er in den Feierabend geht, sammelt sich im Hintergrund ein Stau an Prozessen, die auf Rückmeldung warten. Am Montagmorgen stellt das Team fest, dass die Backups der restlichen neun Systeme nie gelaufen sind, weil die Schleife beim ersten Fehler einfach stehen blieb. Ich habe solche Szenarien oft erlebt. Es fängt harmlos an, aber ohne das Wissen um die Fallstricke der Shell-Programmierung endet es im Chaos. Kleine Fehler in der Syntax oder Logik kosten hier kein virtuelles Spielgeld, sondern echte Arbeitsstunden und im schlimmsten Fall Kundendaten.

Die Falle der statischen Zahlenreihen und warum For I In 1..10 Bash in der Produktion gefährlich ist

Der wohl häufigste Fehler, den ich bei Anfängern sehe, ist der blinde Glaube an statische Sequenzen. Wer For I In 1..10 Bash nutzt, geht davon aus, dass die Welt morgen noch genauso aussieht wie heute. In einem statischen Skript wird hart codiert, dass zehn Iterationen stattfinden sollen. Aber was passiert, wenn morgen der elfte Server dazu kommt? Oder wenn Server Nummer fünf wegen Wartungsarbeiten abgeschaltet wird? Das Skript läuft stumpf weiter. Es versucht, eine Verbindung zu etwas aufzubauen, das nicht existiert, wartet auf Timeouts und verschwendet wertvolle Zeit. Verpassen Sie nicht unseren letzten Bericht zu diesen verwandten Artikel.

In der echten Praxis ist diese Herangehensweise brandgefährlich. Ich erinnere mich an einen Fall bei einem mittelständischen Provider, bei dem ein ähnliches Skript zur Speicherplatzprüfung eingesetzt wurde. Die Schleife war fest auf eine bestimmte Anzahl an Verzeichnissen eingestellt. Als die Infrastruktur wuchs, wurden die neuen Verzeichnisse schlicht ignoriert. Das Ergebnis war ein unbemerkter Überlauf einer Festplatte, der ein ganzes Datenbanksystem lahmlegte. Das Problem ist nicht die Schleife an sich, sondern die mangelnde Dynamik. Ein Profi verlässt sich nicht auf eine manuelle Zählung. Er nutzt Werkzeuge, die den Ist-Zustand des Systems in Echtzeit abfragen. Wenn du eine feste Range vorgibst, baust du dir eine technische Schuld auf, die du später mit Zinsen zurückzahlen musst.

Fehlerhafte Variablenbehandlung führt zu Datenverlust

Ein weiterer Punkt, an dem viele scheitern, ist das sogenannte Quoting. Es klingt trivial, aber es ist der Grund für die meisten zerstörten Dateisysteme. Wenn du innerhalb einer Schleife mit Variablen arbeitest und vergisst, diese in Anführungszeichen zu setzen, interpretiert die Shell Leerzeichen als Trenner. Für einen weiteren Ansatz auf dieses Ereignis empfehlen wir das jüngste Update von Computer Bild.

Nehmen wir ein reales Beispiel aus der Praxis eines Systemadministrators. Er möchte Dateien verschieben, deren Namen Leerzeichen enthalten, etwa "Rechnung Mai.pdf". Ohne korrekte Anführungszeichen versucht das Skript, eine Datei namens "Rechnung" und eine Datei namens "Mai.pdf" zu finden. Beide existieren nicht. Schlimmer wird es bei Löschbefehlen. Ein falsch gesetztes Leerzeichen in einer Variablen kann dazu führen, dass das Skript im Wurzelverzeichnis landet und dort Schaden anrichtet. Ich habe Leute gesehen, die ganze Home-Verzeichnisse geleert haben, nur weil sie dachten, einfache Variablen ohne Schutz seien sicher. Das ist kein Anfängerfehler, den man belächelt, das ist grobe Fahrlässigkeit, die dich den Job kosten kann.

Das Problem mit der Shell-Expansion

Die Shell macht Dinge, die du nicht siehst. Wenn du eine Sequenz wie {1..10} nutzt, wird diese expandiert, bevor der Befehl überhaupt ausgeführt wird. Bei zehn Elementen ist das kein Thema. Aber ich habe Versuche gesehen, bei denen Leute versuchten, Millionen von Dateien so zu verarbeiten. Die Folge: "Argument list too long". Die Shell bricht ab, weil der Speicher für die Befehlszeile erschöpft ist. Hier trennt sich die Spreu vom Weizen. Wer wirklich Erfahrung hat, nutzt Pipes und Tools wie find in Kombination mit xargs oder while read-Schleifen. Das ist robuster und skaliert.

Ignorierte Exit-Codes und das Schweigen der Skripte

Ein Skript, das keine Fehler meldet, ist ein schlechtes Skript. In einer typischen Schleife wird ein Befehl nach dem anderen abgearbeitet. Wenn der dritte Befehl fehlschlägt, macht die Schleife einfach mit dem vierten weiter, als wäre nichts gewesen. Das ist das Rezept für eine Katastrophe.

Stell dir vor, du schreibst ein Skript, das Datenbank-Dumps erstellt und diese dann auf einen Remote-Speicher verschiebt. Der Dump schlägt fehl, weil die Platte voll ist. Das Skript merkt es nicht, greift sich die leere Datei (oder die alte vom Vortag) und schiebt sie auf den Backup-Server. Du denkst, du bist sicher, bis der Ernstfall eintritt und du feststellst, dass deine Backups seit Wochen nur aus 0-Byte-Dateien bestehen. Ein Profi prüft nach jedem kritischen Schritt den Exit-Status. In der Shell ist das die Variable $?. Wenn dieser Wert nicht Null ist, ist etwas schiefgelaufen. Wer das ignoriert, handelt unverantwortlich. In meiner Laufbahn habe ich mehr Zeit damit verbracht, kaputte Backups zu fixen, als die eigentlichen Systeme zu warten, nur weil jemand zu faul war, eine einfache Fehlerprüfung einzubauen.

Parallelisierung ist kein Hexenwerk aber oft falsch verstanden

Wenn Aufgaben Zeit kosten, etwa das Komprimieren von großen Bilddateien, kommen viele auf die Idee, die Schleifenprozesse in den Hintergrund zu schieben. Sie setzen ein Ampersand-Zeichen am Ende des Befehls. Das Problem: Die Schleife feuert alle Prozesse gleichzeitig ab. Wenn du eine Schleife hast, die 1000 Bilder gleichzeitig konvertieren will, geht dein Server in die Knie. Der Load schießt in die Höhe, der Arbeitsspeicher läuft voll, und das System wird instabil.

Die Lösung durch kontrollierte Nebenläufigkeit

Statt blind alles gleichzeitig zu starten, muss man die Last limitieren. Es gibt Tools wie GNU Parallel oder man nutzt einfache Zähler, um sicherzustellen, dass nur eine bestimmte Anzahl an Prozessen gleichzeitig läuft. Ich habe einmal gesehen, wie ein Webserver komplett wegbrach, weil ein Cronjob im Hintergrund meinte, 500 API-Abfragen gleichzeitig in einer Schleife starten zu müssen. Der API-Anbieter hat die IP sofort gesperrt, und die Seite war offline. Das hätte man mit einer ordentlichen Warteschlange verhindern können.

Der Vorher-Nachher-Vergleich in der Praxis

Schauen wir uns an, wie ein typischer Versuch eines Neulings aussieht und wie ein erfahrener Praktiker die Sache angeht. Der Neuling schreibt ein Skript, das eine Liste von IP-Adressen anpingt, um die Verfügbarkeit zu prüfen. Er nutzt eine einfache Schleife, schreibt die Ergebnisse in eine Textdatei und hofft das Beste. Wenn eine IP nicht erreichbar ist, wartet der ping-Befehl sekundenlang auf eine Antwort. Bei 50 Adressen dauert das Skript ewig. Wenn er das Skript zwischendurch abbricht, ist die Ergebnisdatei korrupt oder unvollständig. Es gibt keine Zeitstempel, keine Fehlerlogs, nichts.

Der erfahrene Praktiker hingegen baut das Skript anders auf. Er verwendet zuerst ein Timeout für den Ping-Befehl, damit das Skript nicht bei einer toten Verbindung hängen bleibt. Er schreibt die Ergebnisse nicht direkt in die finale Datei, sondern nutzt temporäre Dateien oder loggt direkt in das System-Log (syslog), damit man auch später noch nachvollziehen kann, was passiert ist. Er prüft, ob er überhaupt die nötigen Berechtigungen hat, bevor er startet. Er baut eine Falle (Trap) ein, die aufräumt, falls das Skript manuell mit STRG+C beendet wird. Das Ergebnis ist ein Werkzeug, das nicht nur funktioniert, wenn alles perfekt ist, sondern auch dann verlässliche Daten liefert, wenn das Netzwerk Probleme macht. Der Unterschied liegt nicht in der Komplexität des Codes, sondern in der Antizipation von Fehlern.

Warum For I In 1..10 Bash oft das falsche Werkzeug ist

Es gibt eine unangenehme Wahrheit in der IT: Nur weil man etwas mit einem Hammer machen kann, ist es noch lange kein Nagel. Viele Aufgaben, die in mühsamen Shell-Schleifen gelöst werden, gehören eigentlich in die Hände spezialisierter Tools. Wer Konfigurationen auf zehn Servern gleichzeitig ändern will, sollte nicht zur Shell greifen, sondern zu Ansible, Puppet oder SaltStack.

💡 Das könnte Sie interessieren: bat out of the hell

Diese Werkzeuge sind idempotent. Das bedeutet, du kannst sie immer wieder ausführen, und sie sorgen dafür, dass das System am Ende im gewünschten Zustand ist. Eine handgestrickte Schleife hingegen macht jedes Mal genau das, was drinsteht. Wenn du eine Zeile an eine Datei anhängst, tut sie das bei jedem Durchlauf wieder. Nach zehn Testläufen hast du die Zeile zehnmal in der Datei. Ich habe Systeme gesehen, bei denen die /etc/hosts Datei mehrere tausend Zeilen lang war, weil ein Skript bei jedem Cron-Run den gleichen Eintrag hinzugefügt hat. Das ist peinlich und zeigt, dass die Grundlagen der Automatisierung nicht verstanden wurden. Die Shell ist super für schnelle, einmalige Aufgaben oder zum Verknüpfen von Programmen, aber sie ist kein Ersatz für ordentliches Konfigurationsmanagement.

Performance-Killer Subshells und externe Aufrufe

Ein technischer Aspekt, der oft unterschätzt wird, ist der Overhead von Prozessaufrufen. In einer Schleife wird bei jedem Durchlauf ein neuer Prozess gestartet, wenn du externe Befehle wie grep, sed oder awk nutzt. Bei zehn Iterationen merkst du das nicht. Wenn das Skript aber über tausende Zeilen einer Log-Datei läuft, summiert sich das.

Ich habe ein Skript optimiert, das zur Auswertung von Webserver-Logs geschrieben wurde. Der ursprüngliche Autor rief innerhalb einer Schleife für jede Zeile dreimal awk auf. Das Skript lief über eine Stunde für eine mittelgroße Datei. Indem wir die Logik direkt in ein einziges awk-Skript verlagerten, das die Datei nur einmal liest, sank die Laufzeit auf unter zehn Sekunden. Die Shell ist langsam, wenn es um Textverarbeitung in großen Mengen geht. Man muss wissen, wann man die Schleife verlässt und die Arbeit an spezialisierte Tools übergibt, die für das Streaming von Daten gebaut wurden.

Realitätscheck

Kommen wir zum Punkt. Wenn du glaubst, dass du mit ein paar Zeilen Shell-Code komplexe Infrastrukturen sicher verwalten kannst, liegst du falsch. Die Shell verzeiht nichts. Ein vertipptes Zeichen, ein vergessenes Anführungszeichen oder eine fehlerhafte Annahme über den Zustand deines Dateisystems können verheerende Folgen haben.

Erfolg in diesem Bereich kommt nicht durch das Auswendiglernen von Befehlen, sondern durch eine paranoide Grundeinstellung. Du musst dich bei jeder Zeile fragen: Was passiert, wenn dieser Befehl fehlschlägt? Was passiert, wenn die Eingabe leer ist? Was passiert, wenn die Platte voll ist? Wenn du diese Fragen nicht beantwortest, baust du keine Automatisierung, sondern eine Zeitbombe. Es gibt keine Abkürzung zur Erfahrung. Du wirst Fehler machen, aber sorge dafür, dass sie in einer Testumgebung passieren und nicht auf dem Hauptserver deines wichtigsten Kunden. Wahre Meisterschaft bedeutet zu wissen, wann man die Shell besser im Werkzeugkasten lässt und zu einer echten Programmiersprache oder einem spezialisierten Tool greift. Wer das ignoriert, bleibt ein ewiger Bastler, der mehr Zeit mit dem Löschen von Bränden verbringt als mit dem Aufbau stabiler Systeme. So ist die Realität in der IT — hart, direkt und ohne Mitleid für schlecht geschriebenen Code.

MS

Martin Schulz

Martin Schulz hat für verschiedene Online-Redaktionen gearbeitet und steht für Qualitätsjournalismus mit Substanz.