Zum Inhalt springen
Techlogia — KI- und Web-Dienstleister Berlin

Bash-Skript schreiben lernen (mit Übungen)

Ein Bash-Skript bündelt Befehle, die du sonst einzeln tippst, in eine wiederholbare Datei. Genau das macht Admins schnell. Hier schreibst du dein erstes Skript Schritt für Schritt – und führst es direkt auf einer echten VM aus.

Shebang und Ausführbarkeit

Jedes Skript beginnt mit #!/bin/bash – dem Shebang, der dem System sagt, womit die Datei ausgeführt wird. Mit chmod +x machst du sie ausführbar. Genau hier verbindet sich Bash mit dem Thema Dateirechte.

Variablen und Argumente

Werte speicherst du in Variablen (name="wert"), Eingaben kommen über $1, $2 ins Skript. So wird aus einem starren Ablauf ein flexibles Werkzeug.

Schleifen und Bedingungen

Mit for/while-Schleifen und if-Bedingungen automatisierst du Wiederholungen und triffst Entscheidungen – die Grundlage jeder echten Automatisierung.

Warum ein Skript anders scheitert als ein Befehl

Ein Skript läuft ohne Zuschauer. Was du im Terminal sofort siehst – eine Fehlermeldung, eine Rückfrage – verschwindet in einem Cron-Lauf spurlos. Deshalb gehört an den Anfang set -euo pipefail: -e bricht bei einem Fehler ab, -u bei einer nicht gesetzten Variablen, pipefail auch dann, wenn nur ein Glied einer Pipe scheitert. Ohne diese Zeile läuft ein kaputtes Skript fröhlich weiter und meldet am Ende Erfolg.

Anführungszeichen sind keine Kosmetik

rm $datei und rm "$datei" sind zwei verschiedene Befehle, sobald der Dateiname ein Leerzeichen enthält: Ohne Anführungszeichen zerlegt die Shell den Wert in mehrere Argumente. Dieselbe Regel gilt für $@ gegenüber "$@". Fast jeder Datenverlust durch ein Bash-Skript geht auf ein fehlendes Anführungszeichen zurück.

Ausgabe trennen: was gehoert nach stdout, was nach stderr

Ein Skript hat zwei Ausgabekanäle. Ergebnisse gehören nach stdout, Meldungen über den Ablauf nach stderr – geschrieben mit echo "…" >&2. Der Unterschied wird wichtig, sobald jemand die Ausgabe weiterverarbeitet: ergebnis=$(mein_skript) fängt nur stdout, und deine Fortschrittsmeldungen landen nicht versehentlich mitten in den Daten.

Aufraeumen, auch wenn es schiefgeht

Legt dein Skript eine temporäre Datei an, muss sie auch bei einem Abbruch verschwinden. trap 'rm -f "$tmp"' EXIT hängt eine Aufräumaktion an das Skriptende – egal ob es normal endet, an set -e abbricht oder mit Strg + C abgeschossen wird. Ohne trap füllt ein regelmäßig laufendes Skript über Monate unbemerkt /tmp.

Rueckgabewerte: woran ein Skript Erfolg erkennt

Jeder Befehl hinterlässt einen Rückgabewert: 0 heißt Erfolg, alles andere Misserfolg. In $? steht der letzte. Darauf bauen && und || auf, und darauf baut auch der Aufrufer deines Skripts – ein Cron-Job, eine Überwachung, eine Auslieferungskette. Ein Skript, das bei einem Fehler trotzdem 0 zurückgibt, meldet Erfolg für etwas, das nicht passiert ist. Deshalb gehört an das Ende ein bewusstes exit 0 oder ein passender Wert.

Was oft schiefgeht

Der häufigste Fehler ist ein Skript, das nur im eigenen Verzeichnis funktioniert: relative Pfade brechen, sobald Cron es aus / startet. Der zweitthäufigste ist eine Pipe, deren erstes Glied scheitert – ohne pipefail zählt nur das letzte, und false | echo ok gilt als Erfolg. Der dritte ist Nachlässigkeit beim Löschen: rm -rf "$verzeichnis/"* mit leerer Variable zeigt auf das Wurzelverzeichnis.

Vom Einzeiler zum wiederverwendbaren Werkzeug

Ein Skript wird brauchbar, wenn es sich erklären kann. Eine kurze usage()-Funktion, die bei fehlenden Argumenten oder bei -h ausgegeben wird, spart dir in drei Monaten die Suche im eigenen Quelltext. Dazu gehören sprechende Variablennamen und Funktionen statt copy-and-paste: Wer denselben Block dreimal im Skript hat, hat ihn beim nächsten Fehler dreimal zu ändern und wird eine Stelle vergessen. Das ist keine Stilfrage, sondern der Unterschied zwischen einem Skript, das im Betrieb überlebt, und einem, das nach der ersten Änderung ersetzt wird.

Befehle zum Ausprobieren

Ein Skript anlegen und ausführbar machen

$ nano sichern.sh$ chmod +x sichern.sh$ ./sichern.sh /tmp/daten

Ohne chmod +x antwortet die Shell mit Permission denied, obwohl die Datei lesbar ist – das Ausführungsrecht ist ein eigenes Bit.

Das Gerüst, das jeden Fehler sichtbar macht

$ #!/usr/bin/env bash$ set -euo pipefail$ ziel="${1:?Pfad angeben}"$ echo "sichere nach $ziel"

${1:?…} bricht mit einer verständlichen Meldung ab, wenn das Argument fehlt – besser als ein leerer Pfad, der stillschweigend ins Wurzelverzeichnis zeigt.

Über Dateien laufen, ohne an Leerzeichen zu scheitern

$ for f in *.log; do$   [ -e "$f" ] || continue$   echo "$f: $(wc -l < "$f") Zeilen"$ done

Die zweite Zeile fängt den Fall ab, dass gar keine Datei passt – sonst durchläuft die Schleife einmal mit dem Muster *.log als Namen.

Temporaere Datei mit garantiertem Aufraeumen

$ tmp=$(mktemp)$ trap 'rm -f "$tmp"' EXIT$ sort eingabe.txt > "$tmp"$ mv "$tmp" ausgabe.txt

mktemp erzeugt einen kollisionsfreien Namen. Das mv am Ende ist atomar – entweder liegt die vollstaendige Datei da oder die alte, nie eine halbe.

Häufige Fehlermeldungen

bash: ./sichern.sh: Permission denied
Ursache: Der Datei fehlt das Ausführungsrecht – lesen darf man sie trotzdem.
Lösung: chmod +x sichern.sh. Alternativ bash sichern.sh, dann startet der Interpreter die Datei direkt.
./sichern.sh: line 3: $'\r': command not found
Ursache: Die Datei hat Windows-Zeilenenden (CRLF). Das Wagenrücklauf-Zeichen am Zeilenende wird als Teil des Befehls gelesen.
Lösung: Mit sed -i 's/\r$//' sichern.sh umstellen oder den Editor auf LF konfigurieren.
sichern.sh: line 7: ziel: unbound variable
Ursache: set -u greift: Die Variable wurde benutzt, aber nie gesetzt – meist ein Tippfehler im Namen.
Lösung: Namen prüfen oder einen Standardwert setzen: ziel="${1:-/tmp}".
syntax error near unexpected token `fi'
Ursache: Ein if ohne abschliessendes then auf derselben oder der naechsten Zeile, oder ein fehlendes Semikolon vor then.
Lösung: Mit bash -n skript.sh pruefen, ohne auszufuehren. Die gemeldete Zeilennummer zeigt auf das SCHLIESSENDE Wort, der Fehler liegt meist darueber.

In fünf Schritten

  1. 01Datei anlegen und mit #!/usr/bin/env bash beginnen – nicht mit dem festen Pfad /bin/bash.
  2. 02set -euo pipefail als zweite Zeile setzen, bevor irgendetwas passiert.
  3. 03Ein Argument einlesen und mit ${1:?…} gegen Vergessen absichern.
  4. 04Mit chmod +x ausführbar machen und einmal ohne Argument starten – die Fehlermeldung muss verständlich sein.
  5. 05Mit bash -n skript.sh die Syntax prüfen, ohne es laufen zu lassen; das gehört vor jeden echten Lauf.

Was du übst

Shebang, chmod +xVariablen & $1/$2for / while / ifset -euo pipefail

Haben Sie ein Projekt?

Lassen Sie uns gemeinsam Ihre Idee in die Tat umsetzen. Wir beraten Sie gerne unverbindlich.

Kontakt aufnehmen

Wie gefällt dir diese Seite?