TASIOMIND.DEV — OPERATIONAL▸▸▸FULL STACK DEVELOPER @ GWQ SERVICEPLUS AG▸▸▸FOUNDER — K8SGPT.AI▸▸▸OPEN SOURCE: ACTIVE▸▸▸DISTRIBUTED SYSTEMS / KUBERNETES / AI▸▸▸RUST + GO + PYTHON▸▸▸FIELD TESTED / STATUS — NOMINAL▸▸▸LOCATION: EUROPE/BERLIN▸▸▸TASIOMIND.DEV — OPERATIONAL▸▸▸FULL STACK DEVELOPER @ GWQ SERVICEPLUS AG▸▸▸FOUNDER — K8SGPT.AI▸▸▸OPEN SOURCE: ACTIVE▸▸▸DISTRIBUTED SYSTEMS / KUBERNETES / AI▸▸▸RUST + GO + PYTHON▸▸▸FIELD TESTED / STATUS — NOMINAL▸▸▸LOCATION: EUROPE/BERLIN▸▸▸

Bash: Kommando-Ausgaben in eine Datei umleiten (Logging)

March 7, 2019

In der Shell-Programmierung ist es oft notwendig, die Ausgabe von Befehlen zur späteren Analyse oder zur Fehlerbehebung in eine Datei zu schreiben. Jedes Kommandozeilen-Programm hat zwei primäre Ausgabeströme:

  • Standardausgabe (stdout, File Descriptor 1): Für normale Programmausgaben.
  • Standardfehlerausgabe (stderr, File Descriptor 2): Für Fehlermeldungen und Diagnosen.

Diese Anleitung zeigt verschiedene Methoden, um diese Ausgabeströme in Dateien umzuleiten.


1. Grundlegende Umleitungsoperatoren

Standardausgabe (stdout) umleiten

  • > (Überschreiben): Leitet stdout in eine Datei um und überschreibt deren Inhalt, falls die Datei bereits existiert.
    code
    ls -l > file.log
    
  • >> (Anhängen): Leitet stdout in eine Datei um und hängt die Ausgabe am Ende an.
    code
    echo "Skript gestartet: $(date)" >> application.log
    

Standardfehlerausgabe (stderr) umleiten

Um stderr umzuleiten, muss explizit der File Descriptor 2 angegeben werden.

code
# Leitet nur Fehlermeldungen in die Datei um
grep "fehler" non_existent_file 2> error.log

2. stdout und stderr kombinieren

In getrennte Dateien umleiten

code
# stdout geht nach out.log, stderr nach err.log
./mein_skript.sh > out.log 2> err.log

In dieselbe Datei umleiten (Bash 4+)

Der &>-Operator ist eine Kurzform, um sowohl stdout als auch stderr in dieselbe Datei umzuleiten.

code
# Überschreibt die Datei mit beiden Ausgabeströmen
./mein_skript.sh &> all.log

# Hängt beide Ausgabeströme an
./mein_skript.sh &>> all.log

In dieselbe Datei umleiten (POSIX-konform)

Diese Methode ist portabler und funktioniert auch in älteren Shells.

code
# Leitet stdout nach all.log und dann stderr dorthin, wo stdout hinzeigt
./mein_skript.sh > all.log 2>&1

Wichtig: Die Reihenfolge 2>&1 ist entscheidend. Würde man 2>&1 > all.log schreiben, würde stderr an den ursprünglichen Ort von stdout (das Terminal) umgeleitet, bevor stdout in die Datei umgeleitet wird.


3. Ausgabe gleichzeitig anzeigen und speichern (tee)

Der tee-Befehl liest von der Standardeingabe und schreibt den Inhalt sowohl in eine Datei als auch auf die Standardausgabe (das Terminal).

code
# Zeigt die Ausgabe von 'ls -l' an UND speichert sie in output.txt
ls -l | tee output.txt

# Hängt die Ausgabe an die Datei an (-a für append)
ls -l | tee -a output.txt

4. Ausgabe eines gesamten Skripts loggen

Um die gesamte Ausgabe eines Skripts (alle Befehle) in eine Datei zu loggen, können Sie den exec-Befehl am Anfang des Skripts verwenden.

code
#!/usr/bin/env bash

LOG_FILE="script_run.log"

# Leitet alle nachfolgenden stdout- und stderr-Ausgaben in die Log-Datei um
# und zeigt sie gleichzeitig über 'tee' im Terminal an.
exec &> >(tee -a "$LOG_FILE")

echo "Diese Zeile wird im Terminal angezeigt und in die Log-Datei geschrieben."
echo "Das gilt auch für Fehlermeldungen." >&2

Fazit

Die Kontrolle über stdout und stderr ist fundamental für das Schreiben robuster und gut diagnostizierbarer Bash-Skripte. Während die grundlegenden Umleitungsoperatoren (>, >>, 2>) für die meisten Anwendungsfälle ausreichen, bieten tee und exec erweiterte Möglichkeiten für interaktives Logging und die Protokollierung ganzer Skript-Abläufe.