# tee — Ausgaben gleichzeitig anzeigen und in Dateien schreiben

> Praxis-Guide zu tee — von der Standardeingabe lesen und gleichzeitig auf den Bildschirm und in mehrere Dateien schreiben. Ideal zum Mitloggen in Pipelines.

Source: https://www.jpkc.com/db/cheatsheets/files-text/tee/

<!-- PROSE:intro -->
tee liest von der Standardeingabe und schreibt das Ergebnis gleichzeitig auf die Standardausgabe und in eine oder mehrere Dateien – wie ein T-Stück in einer Rohrleitung, das den Datenstrom abzweigt. Damit siehst du die Ausgabe eines Befehls live auf dem Bildschirm und protokollierst sie zugleich in eine Datei, ohne die Pipeline zu unterbrechen. Standardmäßig überschreibt tee die Zieldatei; mit `-a` hängst du stattdessen an. Sein bekanntester Trick ist das `sudo tee`-Muster: Weil eine Umleitung mit `>` von der Shell und nicht von `sudo` ausgeführt wird, ist `… | sudo tee datei` der saubere Weg, um in root-eigene Dateien zu schreiben.
<!-- PROSE:intro:end -->

## Grundlagen

`<command> | tee <file>` — Schreibt die Befehlsausgabe sowohl auf den Bildschirm als auch in eine Datei (überschreibt die Datei).

```bash
ls -la | tee listing.txt
```

`<command> | tee -a <file>` — Hängt die Ausgabe an eine Datei an, statt sie zu überschreiben.

```bash
echo 'new entry' | tee -a log.txt
```

`<command> | tee <file1> <file2>` — Schreibt die Ausgabe gleichzeitig in mehrere Dateien.

```bash
date | tee log1.txt log2.txt backup.txt
```

`<command> | tee /dev/stderr` — Dupliziert die Ausgabe nach stderr (praktisch zum Loggen in Pipelines).

```bash
curl -s api.example.com | tee /dev/stderr | jq '.data'
```

## Pipeline-Muster

`<cmd1> | tee <file> | <cmd2>` — Sichert die Zwischenausgabe und setzt die Pipeline fort.

```bash
cat data.csv | tee raw-backup.csv | sort -t',' -k2 > sorted.csv
```

`<cmd1> | tee >(cmd2) | <cmd3>` — Sendet die Ausgabe per Prozesssubstitution an einen Befehl UND setzt die Pipeline fort.

```bash
ls -la | tee >(grep '.log' > logs.txt) | wc -l
```

`<cmd1> | tee >(cmd2) >(cmd3) > /dev/null` — Verteilt die Ausgabe an mehrere Befehle, ohne sie im Terminal anzuzeigen.

```bash
cat data.txt | tee >(wc -l > count.txt) >(grep ERROR > errors.txt) > /dev/null
```

`<command> 2>&1 | tee <file>` — Erfasst stdout und stderr in einer Datei und zeigt beides an.

```bash
make build 2>&1 | tee build.log
```

## Schreiben mit erhöhten Rechten

`echo '<text>' | sudo tee <file>` — Schreibt in eine root-eigene Datei (eine Umleitung mit `>` allein funktioniert mit sudo nicht).

```bash
echo 'nameserver 8.8.8.8' | sudo tee /etc/resolv.conf
```

`echo '<text>' | sudo tee -a <file>` — Hängt an eine root-eigene Datei an.

```bash
echo '192.168.1.100 myserver' | sudo tee -a /etc/hosts
```

`echo '<text>' | sudo tee <file> > /dev/null` — Schreibt in eine root-eigene Datei, ohne die Ausgabe auf dem Bildschirm anzuzeigen.

```bash
echo 'vm.swappiness=10' | sudo tee /etc/sysctl.d/99-swap.conf > /dev/null
```

`cat <source> | sudo tee <dest> > /dev/null` — Kopiert eine Datei an einen root-eigenen Ort.

```bash
cat nginx.conf | sudo tee /etc/nginx/sites-available/mysite > /dev/null
```

## Logging & Debugging

`<script> 2>&1 | tee -a <logfile>` — Führt ein Skript aus und protokolliert die gesamte Ausgabe (stdout + stderr) im Anhängemodus.

```bash
./deploy.sh 2>&1 | tee -a /var/log/deploy.log
```

`script -q /dev/null <command> | tee <file>` — Erfasst Ausgaben von Befehlen, die eine Nicht-Terminal-Ausgabe erkennen.

```bash
script -q /dev/null ls --color | tee colored-output.txt
```

`<command> | tee >(logger -t <tag>)` — Sendet die Pipeline-Ausgabe per Prozesssubstitution an syslog.

```bash
backup.sh 2>&1 | tee >(logger -t backup)
```

`<command> | tee >(ts '[%Y-%m-%d %H:%M:%S]' >> <logfile>)` — Versieht die protokollierte Ausgabe mit Zeitstempeln per ts (aus moreutils).

```bash
tail -f /var/log/app.log | tee >(ts '[%Y-%m-%d %H:%M:%S]' >> timestamped.log)
```

## Typische Anwendungsfälle

`tar czf - <dir> | tee <archive> | md5sum` — Erzeugt ein Archiv und berechnet in einem Durchgang seine Prüfsumme.

```bash
tar czf - /var/www | tee backup.tar.gz | md5sum > backup.md5
```

`<command> | tee /dev/tty | <next_command>` — Zeigt die Ausgabe im Terminal an und leitet sie zugleich an den nächsten Befehl weiter.

```bash
find . -name '*.log' | tee /dev/tty | xargs rm
```

`echo '<config>' | tee <file1> <file2> <file3> > /dev/null` — Schreibt denselben Inhalt auf einmal in mehrere Konfigurationsdateien.

```bash
echo 'export NODE_ENV=production' | tee .env .env.local > /dev/null
```

`diff <(command1) <(command2) | tee diff-output.txt` — Vergleicht zwei Befehlsausgaben und speichert den Diff.

```bash
diff <(curl -s api.example.com/v1) <(curl -s api.example.com/v2) | tee api-diff.txt
```

`cat <<'EOF' | sudo tee <file> > /dev/null\n<content>\nEOF` — Schreibt ein mehrzeiliges Here-Dokument in eine root-eigene Datei.

```bash
cat <<'EOF' | sudo tee /etc/nginx/conf.d/app.conf > /dev/null
server {
    listen 80;
    server_name example.com;
}
EOF
```

<!-- PROSE:outro -->
## Fazit

tee schließt die Lücke zwischen „auf dem Bildschirm sehen" und „in eine Datei schreiben" – unverzichtbar beim Mitloggen von Build- und Deploy-Läufen, beim Schreiben in root-eigene Dateien (`sudo tee`) und beim Aufzweigen eines Stroms an mehrere Ziele per Prozesssubstitution. Achte auf zwei Dinge: tee überschreibt ohne Vorwarnung, wenn du `-a` vergisst – beim Loggen ist `-a` fast immer die richtige Wahl. Und um Fehlermeldungen mit aufzuzeichnen, leitest du stderr vorher mit `2>&1` auf stdout um, denn tee sieht nur den stdout-Strom der Pipe. Den Exit-Status liefert in einer Pipe standardmäßig der letzte Befehl, also tee selbst; brauchst du den des eigentlichen Befehls, setze `set -o pipefail`.

## Weiterführende Links

- [GNU coreutils: tee](https://www.gnu.org/software/coreutils/manual/html_node/tee-invocation.html) – offizielle Referenz mit allen Optionen (englisch)
- [ubuntuusers-Wiki: tee](https://wiki.ubuntuusers.de/tee/) – deutschsprachige Dokumentation zu tee
<!-- PROSE:outro:end -->

## Verwandte Kommandos

- [xargs](https://www.jpkc.com/db/cheatsheets/files-text/xargs/) – Eingaben zu Argumenten für weitere Befehle aufbereiten
- [tail](https://www.jpkc.com/db/cheatsheets/files-text/tail/) – Logdateien live mitlesen, oft als Gegenstück zu tee-Logs
- [less](https://www.jpkc.com/db/cheatsheets/files-text/less/) – große Ausgaben und Logdateien seitenweise durchblättern

