Bash-Skript für Einsteiger: erstes Skript, Variablen, Bedingungen, Schleifen und cron
Ein Bash-Skript ist eine Textdatei mit Shell-Befehlen, die mit der Zeile #!/bin/bash beginnt, per chmod +x das Ausführungsrecht erhält und als ./skript.sh gestartet wird. Skripte nutzen Variablen, die Argumente $1 und $2, if-Bedingungen, for- und while-Schleifen; regelmäßige Ausführung richten Sie mit crontab -e ein.
Ein Bash-Skript ist eine einfache Textdatei mit Befehlen, die Sie sonst einzeln im Terminal eintippen würden. Das Skript beginnt mit der Shebang-Zeile #!/bin/bash, erhält per chmod +x das Ausführungsrecht und wird als ./skript.sh gestartet. Diese Anleitung für Einsteiger führt Sie von der ersten Zeile bis zur zeitgesteuerten Ausführung: Variablen, Argumente, Bedingungen, Schleifen, Fehlerbehandlung und cron.
Das erste Bash-Skript in einer Minute
Legen Sie eine Datei in einem beliebigen Editor an, zum Beispiel nano:
nano hallo.sh
#!/bin/bash
# Erstes Skript: Begrüßung und ein paar Systeminformationen
echo "Hallo, $USER!"
echo "Heute: $(date +%Y-%m-%d)"
echo "Sie befinden sich in: $(pwd)"
Speichern Sie (Strg+O, Enter, Strg+X), geben Sie das Ausführungsrecht und starten Sie das Skript:
$ chmod +x hallo.sh
$ ./hallo.sh
Hallo, alice!
Heute: 2026-10-12
Sie befinden sich in: /home/alice
Zeilen, die mit # beginnen, sind Kommentare. $(befehl) fügt die Ausgabe eines Befehls direkt in die Zeile ein.
Shebang: wozu die erste Zeile dient
Die Zeile #!/bin/bash sagt dem System, mit welchem Interpreter die Datei ausgeführt werden soll. Ohne sie läuft das Skript in der Shell, die gerade verfügbar ist; auf manchen Systemen ist /bin/sh nicht bash, sondern das einfachere dash, wo einige Konstrukte nicht funktionieren.
Häufig begegnet man auch #!/usr/bin/env bash: Es sucht bash im PATH, was praktisch ist, wenn bash nicht in /bin installiert ist.
Wie man ein Skript startet und warum ./
Es gibt zwei Wege:
./hallo.sh— braucht Shebang und das Rechtx. Das Präfix./ist Pflicht, weil das aktuelle Verzeichnis nicht imPATHsteht.bash hallo.sh— kein Ausführungsrecht nötig, der Interpreter wird ausdrücklich angegeben.
Sehen Sie command not found ohne ./ oder Permission denied ohne chmod +x, sind genau das die beiden Ursachen. Damit Sie Ihre Skripte von überall per Namen aufrufen können, legen Sie sie in ~/bin oder /usr/local/bin.
Variablen
Eine Variable wird ohne Leerzeichen um das = zugewiesen und mit $ gelesen:
#!/bin/bash
name="backup"
verzeichnis="/var/backups"
heute=$(date +%F)
echo "Datei: ${verzeichnis}/${name}-${heute}.tar.gz"
Geschweifte Klammern trennen den Variablennamen vom umgebenden Text. Die Zeile name = "backup" mit Leerzeichen ist ein Fehler: bash versucht dann, einen Befehl namens name auszuführen.
Anführungszeichen sind wichtig
In doppelten Anführungszeichen werden Variablen ersetzt, in einfachen nicht. Variablen sollte man fast immer in doppelte Anführungszeichen setzen, sonst wird ein Dateiname mit Leerzeichen in zwei Argumente zerlegt.
datei="mein bericht.txt"
rm $datei # Fehler: versucht „mein“ und „bericht.txt“ zu löschen
rm "$datei" # richtig
echo '$HOME' # gibt wörtlich $HOME aus
echo "$HOME" # gibt /home/alice aus
Umgebungsvariablen
Variablen wie $HOME, $USER und $PATH setzt das System. Eine eigene Variable reichen Sie mit export an Kindprozesse weiter. Dauerhafte Einstellungen der Umgebung gehören in ~/.bashrc oder ~/.profile.
Argumente des Skripts
Werte, die beim Start übergeben werden, stehen als $1, $2 usw. zur Verfügung.
| Variable | Was sie enthält |
|---|---|
$0 | der Name des Skripts |
$1, $2… | das erste, zweite Argument |
$# | die Anzahl der Argumente |
"$@" | alle Argumente, jedes einzeln |
$? | Exitcode des letzten Befehls |
$$ | PID des aktuellen Skripts |
#!/bin/bash
echo "Skript $0 hat $# Argument(e) erhalten"
echo "Erstes: $1"
$ ./argumente.sh nginx 80
Skript ./argumente.sh hat 2 Argument(e) erhalten
Erstes: nginx
Eine Eingabe des Benutzers liest der Befehl read: read -p "Name eingeben: " name.
if-Bedingungen
Jeder Befehl liefert einen Exitcode: 0 bedeutet Erfolg, alles andere einen Fehler. Die Konstruktion if prüft genau diesen Code. Für Vergleiche verwendet man [[ ... ]]; die Leerzeichen innerhalb der Klammern sind Pflicht.
#!/bin/bash
if [[ $# -eq 0 ]]; then
echo "Verwendung: $0 <verzeichnis>"
exit 1
fi
if [[ -d "$1" ]]; then
echo "Verzeichnis $1 existiert"
elif [[ -f "$1" ]]; then
echo "$1 ist eine Datei, kein Verzeichnis"
else
echo "$1 nicht gefunden"
fi
| Prüfung | Bedeutung |
|---|---|
-f datei | eine gewöhnliche Datei existiert |
-d verzeichnis | ein Verzeichnis existiert |
-e pfad | der Pfad existiert |
-x datei | die Datei ist ausführbar |
-z "$var" / -n "$var" | die Zeichenkette ist leer / nicht leer |
"$a" == "$b", != | Zeichenkettenvergleich |
-eq -ne -lt -le -gt -ge | Zahlenvergleich |
Sie können auch jeden Befehl direkt prüfen:
if systemctl is-active --quiet nginx; then
echo "nginx läuft"
else
echo "nginx ist gestoppt"
fi
Bei vielen Varianten ist case bequem:
case "$1" in
start) echo "Starte" ;;
stop) echo "Stoppe" ;;
*) echo "Unbekannter Befehl: $1"; exit 1 ;;
esac
for- und while-Schleifen
for: über eine Liste iterieren
for host in web1 web2 db1; do
echo "Prüfe $host"
ping -c 1 -W 1 "$host" > /dev/null && echo " erreichbar" || echo " nicht erreichbar"
done
for datei in /var/log/*.log; do
echo "$datei: $(wc -l < "$datei") Zeilen"
done
for i in {1..5}; do
echo "Versuch $i"
done
while: solange die Bedingung gilt
Ein klassisches Beispiel ist das zeilenweise Lesen einer Datei:
while read -r benutzer; do
echo "Benutzer: $benutzer"
done < benutzer.txt
Und das Warten, bis ein Dienst hochgefahren ist:
zaehler=0
until curl -sf http://localhost:8080/health > /dev/null; do
zaehler=$((zaehler + 1))
if [[ $zaehler -ge 10 ]]; then
echo "Dienst ist nicht gestartet"
exit 1
fi
sleep 3
done
echo "Dienst ist bereit"
Arithmetik schreibt man in bash in doppelten Klammern: $((a + b)). Sie funktioniert nur mit ganzen Zahlen.
Funktionen
Wiederkehrenden Code lagert man in Funktionen aus. Innerhalb einer Funktion sind die Argumente dieselben $1, $2, und local verhindert, dass eine Variable nach außen dringt.
protokoll() {
local stufe="$1"; shift
echo "$(date '+%F %T') [$stufe] $*"
}
protokoll INFO "Starte die Sicherung"
protokoll ERROR "Kein Speicherplatz mehr"
Fehlerbehandlung: set -euo pipefail
Standardmäßig setzt bash nach einem fehlgeschlagenen Befehl fort — so kann ein Sicherungsskript „erfolgreich“ enden, ohne etwas kopiert zu haben. Am Anfang von Skripten setzt man daher oft den strikten Modus:
#!/bin/bash
set -euo pipefail
-e— beim ersten Fehler anhalten.-u— die Verwendung einer nicht gesetzten Variable als Fehler behandeln (schützt vorrm -rf "$DIR/"mit leeremDIR).-o pipefail— eine Pipeline gilt als fehlgeschlagen, wenn irgendein Teil scheitert.
Zum Debuggen starten Sie das Skript mit bash -x skript.sh: bash gibt jeden Befehl vor seiner Ausführung aus. Typische Fehler findet man vor dem Start mit dem Werkzeug shellcheck.
Praxisbeispiel: ein Sicherungsskript
#!/bin/bash
set -euo pipefail
QUELLE="${1:-/var/www}"
ZIEL="/var/backups/site"
AUFBEWAHRUNG_TAGE=7
ZEITSTEMPEL=$(date +%F_%H-%M)
mkdir -p "$ZIEL"
tar -czf "$ZIEL/site-$ZEITSTEMPEL.tar.gz" -C "$(dirname "$QUELLE")" "$(basename "$QUELLE")"
echo "Archiv erstellt: $ZIEL/site-$ZEITSTEMPEL.tar.gz"
# Archive löschen, die älter als AUFBEWAHRUNG_TAGE Tage sind
find "$ZIEL" -name "site-*.tar.gz" -mtime +"$AUFBEWAHRUNG_TAGE" -delete
Die Schreibweise ${1:-/var/www} bedeutet „das erste Argument, und falls keines da ist, /var/www“. Speichern Sie das Skript als /usr/local/bin/backup-site.sh und machen Sie es ausführbar: sudo chmod +x /usr/local/bin/backup-site.sh.
Regelmäßige Ausführung: cron
Cron ist der Dienst, der Befehle nach Zeitplan startet. Die Aufgaben eines Benutzers bearbeiten Sie mit crontab -e, anzeigen lassen sie sich mit crontab -l, die Aufgaben von root mit sudo crontab -e.
Eine Aufgabenzeile besteht aus fünf Zeitfeldern und dem Befehl:
# Minute Stunde Tag_im_Monat Monat Wochentag Befehl
30 2 * * * /usr/local/bin/backup-site.sh >> /var/log/backup.log 2>&1
| Zeitplan | Wann er läuft |
|---|---|
*/5 * * * * | alle 5 Minuten |
0 * * * * | zu Beginn jeder Stunde |
30 2 * * * | jeden Tag um 02:30 |
0 9 * * 1-5 | werktags um 09:00 |
0 3 1 * * | am 1. jedes Monats um 03:00 |
@reboot | einmal nach dem Systemstart |
Warum ein Skript von Hand funktioniert, in cron aber nicht
- Andere Umgebung. Cron startet Aufgaben mit einem minimalen
PATHund ohne Ihre~/.bashrc. Schreiben Sie vollständige Pfade zu Befehlen und Dateien oder setzen SiePATHam Anfang der Crontab. - Anderes aktuelles Verzeichnis. Eine Aufgabe startet im Home-Verzeichnis, nicht dort, wo das Skript liegt. Verwenden Sie absolute Pfade.
- Das Zeichen %. In einer Crontab bedeutet
%einen Zeilenumbruch, deshalb mussdate +%Fdirekt in der Aufgabenzeile als\%geschrieben werden. Einfacher ist es, den Befehl in ein Skript auszulagern. - Die Ausgabe geht verloren. Leiten Sie die Ausgabe in ein Protokoll um (
>> datei 2>&1), sonst sehen Sie die Fehler nicht. Cron-Läufe erscheinen injournalctl -u cron(auf RHEL-artigen Systemen heißt der Dienstcrond).
Auf Systemen mit systemd sind Timer eine Alternative zu cron: Sie schreiben die Ausgabe ins Journal und können verpasste Läufe nachholen.
Fazit
Ein Bash-Skript für Einsteiger ist eine Datei mit der Shebang-Zeile #!/bin/bash, dem Ausführungsrecht und einer Folge von Befehlen. Ergänzen Sie Variablen in Anführungszeichen, eine Argumentprüfung mit if, die Schleifen for und while sowie den strikten Modus set -euo pipefail — und Sie haben ein zuverlässiges Automatisierungswerkzeug, das cron nach Zeitplan ausführen kann. Bash-Skripte, Umgebung und cron behandelt unser Linux-Kurs praxisnah Schritt für Schritt.
Häufige Fragen
Was ist der Unterschied zwischen bash und sh?
sh ist die standardisierte POSIX-Shell, bash ist deren erweiterte Version mit Arrays, doppelten Klammern und weiteren Komfortfunktionen. Ein Skript mit bash-Konstrukten muss mit bash gestartet werden, nicht mit sh.
Welche Dateiendung soll ein Bash-Skript haben?
Linux achtet nicht auf die Endung: Der Interpreter wird durch die Shebang-Zeile bestimmt. Die Endung .sh ist nur eine Konvention, damit Menschen erkennen, dass es ein Skript ist.
Wie übergebe ich ein Passwort sicher an ein Skript?
Übergeben Sie es nicht als Argument — Argumente sind für andere Benutzer in ps sichtbar. Verwenden Sie eine Umgebungsvariable aus einer Datei mit den Rechten 600 oder read -s für eine Eingabe ohne Anzeige.
Wie prüfe ich, ob das Skript als root läuft?
Vergleichen Sie die Benutzer-ID mit null: if [[ $EUID -ne 0 ]]; then echo "root ist erforderlich"; exit 1; fi.
Wie starte ich ein Skript im Hintergrund, damit es nach dem Abmelden von SSH weiterläuft?
Verwenden Sie nohup ./skript.sh &, eine tmux- oder screen-Sitzung, und für den Dauerbetrieb verpacken Sie das Skript in einen systemd-Dienst.
Dieses Thema wird im Kurs „Linux: с нуля до уверенного администрирования“ ausführlich mit Praxis behandelt.
- Bash-скрипты: от команды в терминале до рабочего скрипта автоматизации
- Пакеты, окружение и первая автоматизация: apt, профиль и cron