Inhalt dieses Kapitels
Rückblick + Was kommt heute
EinstiegGestern hast du dich im Terminal eingelebt: Navigation mit
cd, ls und pwd, Dateien anlegen
mit touch, mkdir, cp,
mv und rm, Textdateien mit nano
und vim bearbeiten, einfache Ausgabe mit echo.
Heute kombinieren wir das alles zu Werkzeugketten.
Bis gestern: ls → in Datei speichern → öffnen →
durchsuchen. Heute: ls /etc | grep conf > meine_configs.txt
— alles in einer Zeile. Wildcards, Redirection, Pipes und
grep sind die vier Bausteine, mit denen Admins ihren
Alltag erledigen.
Wildcards (Globbing) — viele Dateien auf einmal
PflichtWildcards (auch „Globs“ genannt) sind Platzhalter,
die die Shell durch passende Dateinamen ersetzt, BEVOR sie
den Befehl ausführt. Damit kannst du ls *.txt sagen — und
die Shell macht intern daraus ls anna.txt bernd.txt clara.txt.
Die vier wichtigsten Wildcards
| Wildcard | Bedeutung | Beispiel |
|---|---|---|
* |
beliebig viele beliebige Zeichen (auch null) | ls *.txt |
? |
GENAU EIN beliebiges Zeichen | ls test?.txt → test1.txt bis testZ.txt |
[abc] |
EIN Zeichen aus der Liste | ls test[135].txt → nur 1, 3, 5 |
[a-z] / [0-9] |
EIN Zeichen aus einem Bereich | ls report-[a-c].txt |
- Backup-Skripte:
tar -czf backup.tar.gz /var/log/*.log.1 - Aufräumen:
rm /tmp/build_*.tmp - Massen-Kopie:
cp ~/Downloads/rechnung_Q1_*.pdf ~/buchhaltung/2026/
▶ Mehr Use Cases im Admin-Alltag
- Reporting:
ls -la /etc/nginx/conf.d/*.conf— welche Configs gibt's? - Selektives Verschieben:
mv *.jpg ~/bilder/ - Pattern-Statistik:
ls /var/log/*.gz | wc -l— wie viele rotierte Logs? - User-Cleanup:
userdel test_user{01..10}(mit Brace Expansion)
Praxis-Beispiele
# Alle .txt-Dateien
ls *.txt
# Genau ein Zeichen
ls test?.txt
# Auswahl
ls test[135].txt
# Bereich
ls report-[a-c].txt
# Alle Dateien, die mit "m" beginnen
ls /usr/bin/m*
# Alle versteckten Dateien (mit Punkt am Anfang)
ls -d .*
Wildcards werden von der Shell aufgelöst, nicht
vom Befehl selbst. rm sieht nie das Sternchen — es
bekommt schon die fertige Liste der Treffer übergeben. Konsequenz:
wenn nichts passt, wird das Sternchen wörtlich
übergeben — das gibt dann unerwartete Fehler.
▶ Tiefer einsteigen: Was ist Globbing?
Der Begriff Globbing kommt vom alten Unix-Tool
glob (global command, 1969) — einem Hilfsprogramm in
frühen Unix-Versionen, das genau diese Aufgabe übernahm: Wildcards
in Dateinamen auflösen. Heute steckt das direkt in der Shell.
Wildcards sind nicht dasselbe wie reguläre
Ausdrücke (Regex). Wildcards arbeiten auf Dateinamen mit einer
kleinen Sprache (* ? [ ]). Regex ist mächtiger, aber
komplizierter — wir teasern das in grep kurz an.
Brace Expansion { }
Bonus
Wildcards matchen existierende Dateien — Brace Expansion generiert Text-Listen, unabhängig davon, ob die Dateien existieren. Damit baust du in einer Zeile, wofür sonst eine Schleife nötig wäre.
# Listen
echo {rot,gelb,blau}
# → rot gelb blau
# Bereiche
echo {1..10}
# → 1 2 3 4 5 6 7 8 9 10
# 10 Dateien auf einmal
touch backup_2024-{01..10}.tar.gz
# Verzeichnisstruktur in einem Rutsch
mkdir -p projekt/{src,docs,tests}/{alt,neu}
- Projektstruktur in 1 Zeile:
mkdir -p projekt/{src,docs,tests,config} - Schnell-Backup:
cp config.ini{,.bak}→ erzeugtconfig.ini.bak - Testdateien generieren:
touch test_{001..100}.txt
▶ Mehr Brace-Tricks
- Datums-Loops:
mkdir backup_2026-{01..12} - Schnell umbenennen:
mv datei.txt{,.alt}→ datei.txt.alt - Mehrere Endungen:
ls *.{txt,log,md} - Testuser-Familie:
useradd test_user_{a,b,c}
ls {*.txt,*.log} funktioniert technisch, aber
ls *.txt *.log ist klarer und verständlicher. Brace
Expansion glänzt da, wo du Listen erzeugen willst, nicht
beim Matchen existierender Dateien.
Redirection — stdin / stdout / stderr umleiten
PflichtJeder Linux-Prozess hat drei Standard-Datenkanäle. Mit Redirection lenkst du diese um — das ist die Basis von allem, was die Shell mächtig macht.
Die wichtigsten Operatoren
| Operator | Bedeutung | Beispiel |
|---|---|---|
> | stdout in Datei (überschreibt!) | ls > liste.txt |
>> | stdout an Datei anhängen | date >> log.txt |
2> | stderr in Datei | cd /nope 2> fehler.log |
&> | stdout UND stderr in Datei | befehl &> alles.log |
> datei 2>&1 | klassisch: beide in eine Datei | befehl > alles.log 2>&1 |
< | stdin aus Datei | sort < unsortiert.txt |
2> /dev/null | Fehler verwerfen | find / -name "x" 2>/dev/null |
- Reports erzeugen:
ls -la /var/log > inventur.txt— zum Mailen oder Archivieren - Snapshot vor Änderungen:
iptables -L > firewall_vorher.txt— Rollback-Referenz - Fehler ausblenden:
find / -name "x.conf" 2>/dev/null— nur Treffer, kein Permission-Denied-Spam
▶ Mehr Use Cases — Redirection in der Praxis
- Log-Aggregation per Cron:
(date; uptime; free -h) >> /var/log/healthcheck.log - Saubere Skript-Ausgabe:
mein_skript.sh > output.log 2> errors.log - Stille Cron-Jobs:
befehl > /dev/null— Cron mailt nur bei Fehlern - Kompletter Mute:
command > /dev/null 2>&1— nur Exit-Code zählt - Schnell-Test ohne Output:
cat datei.txt > /dev/null && echo OK - DB-Dump einspielen:
mysql -u root -p < dump.sql - Remote-Skript mit lokaler Eingabe:
ssh server "befehl" < lokale_eingabe.txt
Live-Demo
# Datum in Logfile schreiben — überschreibt!
date > heute.log
# Datum anhängen — bleibt erhalten
date >> heute.log
# Nur Fehler abfangen
find /etc -name "*.conf" 2> fehler.log
# Output unterdrücken
ls -la /root 2> /dev/null
# Stdout UND stderr in eine Datei — zwei Schreibweisen
befehl &> alles.log # kurz (modern)
befehl > alles.log 2>&1 # klassisch (portabler)
> ist brutal. Ohne Nachfrage,
ohne Backup — Zieldatei wird auf null Bytes geleert und neu
geschrieben. Wenn dir der Inhalt einer Logdatei wichtig ist:
>> benutzen. Ein einziger fehlender Strich kann
das Audit-Log eines ganzen Tages auslöschen.
▶ Tiefer einsteigen: Was ist /dev/null?
/dev/null ist die schwarze Mülltonne
des Systems — alles, was du dort reinschreibst, ist weg. Beim Lesen
ist sie sofort EOF (also leer).
Technisch eine echte Gerätedatei (engl. character device)
im FHS unter /dev/. Verwandte:
/dev/zero— endlose Null-Bytes (für Test-Dateien)/dev/random//dev/urandom— Zufallszahlen-Quellen
Beispiel — 100-MB-Testdatei erzeugen:
dd if=/dev/zero of=test.img bs=1M count=100
Pipes | und tee
Pflicht
Eine Pipe (Pipe-Symbol |, deutsche
Tastatur: AltGr+<) leitet stdout des einen Befehls als stdin in
den nächsten. Damit kannst du kleine Werkzeuge zu großen Workflows
verknüpfen — ohne Zwischendatei.
- Live-Fehler beobachten:
tail -f /var/log/messages | grep -i error - Prozess prüfen:
ps aux | grep nginx - Top-Speicherfresser finden:
du -sh /* 2>/dev/null | sort -h | tail -5
▶ Mehr Pipe-Klassiker
who | wc -l— wie viele User eingeloggtdf -h | grep -v tmpfs— Disk-Belegung kompaktps aux --sort=-%mem | head -10— Top-RAMcat access.log | awk '{print $1}' | sort -u | wc -l— eindeutige IPslast | head -50 | grep -v reboot— Login-Historie ohne Reboots
Live-Demo
# Wie viele Dateien im Verzeichnis?
ls | wc -l
# Wie viele Zeilen hat /etc/passwd?
cat /etc/passwd | wc -l
# Lange Ausgabe in Pages (Enter / Leertaste / q)
ls -la /usr/bin | less
# Sortieren + Duplikate zählen
cat zugriffe.log | sort | uniq -c
# Größte Dateien zuerst
ls -lS /var/log | head -5
tee — die „Y-Weiche"
tee liest stdin und schreibt es gleichzeitig
auf stdout UND in eine Datei. Der Name kommt von „T-Stück" in der
Klempnerei — der Datenstrom verzweigt.
# Schreibt gleichzeitig auf Bildschirm UND in Datei
echo "Wichtige Meldung" | tee log.txt
# An Datei anhängen
echo "Noch eine Zeile" | tee -a log.txt
# Klassiker: Datei mit sudo schreiben
echo "127.0.0.1 test" | sudo tee -a /etc/hosts
tee für sudoDer Klassiker echo "..." | sudo tee -a /etc/...
funktioniert, wo echo "..." >> /etc/...
scheitert: die Umleitung >>
läuft mit deinen User-Rechten, nicht mit sudo-Rechten. Bei
tee hingegen ist der ganze Befehl ein
sudo-Prozess, der die Datei öffnen darf.
▶ Tiefer einsteigen: Warum heißt es Pipe?
Der Begriff geht zurück auf Douglas McIlroy
(Bell Labs, 1972) — er hat das Konzept in Unix eingeführt. Das
Unix-Mantra dazu: „Make each program do one thing well — and to
work together with other programs." Genau das ist die Idee
hinter |.
Technisch laufen die per Pipe verbundenen Befehle
parallel: der zweite Prozess wartet nicht auf
das Ende des ersten, sondern bekommt Datenstrom-Stück für
Datenstrom-Stück. Deshalb funktioniert
tail -f log | grep error live.
grep — der Filter
Pflicht
grep ist das Schweizer Taschenmesser zum Filtern von
Text. Der Name steht für global
regular expression
print — also „durchsuche global nach einem Muster
und drucke die Treffer".
Die wichtigsten Optionen
| Option | Bedeutung |
|---|---|
| (keine) | nur Zeilen mit Muster |
-i | ignore case — Groß-/Kleinschreibung egal |
-v | invert — Zeilen OHNE Muster |
-n | mit Zeilennummern |
-r | rekursiv durch Verzeichnisse |
-c | nur Anzahl der Treffer |
-l | nur Dateinamen mit Treffern |
--color | Treffer farbig hervorheben |
- Fehler-Triage:
grep -i error /var/log/messages - Config-Inspektion:
grep -v "^#" /etc/ssh/sshd_config— nur aktive Zeilen ohne Kommentare - Quick-Audit:
grep -r "192.168.1.100" /etc— wo ist die alte IP konfiguriert?
▶ Mehr grep-Tricks aus dem Admin-Alltag
- Skript-Debugging:
grep -rn "DB_HOST" /opt/myapp - Prozess-Filter ohne sich selbst:
ps aux | grep java | grep -v grep - Nur Dateinamen mit Treffern:
grep -rl "TODO" . - Pre-/Post-Kontext:
grep -A 3 -B 1 "error" log.txt - Mehrere Patterns:
grep -E "error|warning|critical" log.txt - Anzahl statt Inhalt:
grep -c "200 OK" access.log
Praxis-Beispiele
# Klassiker 1: In Datei nach Wort suchen
grep "error" /var/log/messages
# Klassiker 2: Case-insensitiv
grep -i "warning" log.txt
# Klassiker 3: Mit Pipe — Prozesse filtern
ps aux | grep nginx
# Klassiker 4: Zeilen mit Zeilennummer
grep -n "TODO" *.py
# Klassiker 5: Rekursiv in /etc nach IP-Adresse
grep -r "192.168" /etc
# Klassiker 6: Was NICHT passt — Kommentare rausfiltern
grep -v "^#" /etc/ssh/sshd_config
grep im Alltagtail -f /var/log/messages | grep -i error zeigt
live, wenn neue Fehler im Systemlog auftauchen — und ist
damit der wohl wichtigste Pflicht-Skill für jeden Admin. Du
siehst Probleme, sobald sie passieren, nicht erst nach dem
Anruf vom Chef.
▶ Tiefer einsteigen: Reguläre Ausdrücke (kurz)
Das Muster, das du grep übergibst, ist nicht nur
Klartext — es ist ein Regex. Die wichtigsten Bausteine:
^muster→ Zeile beginnt mit „muster"muster$→ Zeile endet mit „muster".→ ein beliebiges Zeichen*→ 0 oder mehr Vorkommen des Vorzeichens[abc]→ eines dieser Zeichen
Beispiel: grep "^error" log.txt — nur Zeilen, die mit
„error" beginnen. Für mächtigere Regex (Alternation,
Quantifier) brauchst du grep -E oder
egrep.
Vorsicht: Das * in Regex ist
nicht dasselbe wie das * in Wildcards.
grep "*.txt" sucht NICHT nach „endet mit .txt".
📧 Von: Markus Becker · IT-Leitung
An: Tim Schulz (du)
Betreff: Webserver-Logs vor dem Audit — bitte vorbereiten
Hi Tim,
kurzfristig nochmal: morgen ist das externe Sicherheits-Audit, und die Auditoren wollen Auszüge aus unseren Webserver-Logs sehen. Bitte bereite Folgendes vor:
- Ein Sammelverzeichnis mit Test-Logs (Sandra schickt dir gleich Beispiele).
- Eine Übersicht: Wie viele Fehler haben wir letzte Woche gehabt? Wie viele Warnings?
- Eine „saubere" Datei, in der alle Kommentare aus unserer Webserver-Config entfernt sind — die Auditoren wollen nur die aktiven Regeln sehen.
- Eine kombinierte Datei mit nur den Errors aus allen Logs.
Setz dich heute Morgen in den ersten Block dran. Mit Wildcards,
Pipes und grep kriegst du das in 30 Minuten erledigt.
Cheat-Sheet liegt auf deinem Schreibtisch.
Danke!
— Markus
- Erstelle
~/audit-lab/und wechsle hinein. - Erstelle die Unterordner
logs/,configs/,output/in einem Befehl (Brace Expansion!). - Erstelle in
logs/mittouchund Brace Expansion die 12 Dateienaccess_2026-01.logbisaccess_2026-12.log. - Bestücke drei der Logs (
access_2026-01.log,access_2026-02.log,access_2026-03.log) jeweils mit ein paar Beispielzeilen — nutze dafürecho "..." >> datei.log(mehrfach hintereinander).
mkdir -p ~/audit-lab
cd ~/audit-lab
mkdir -p {logs,configs,output}
touch logs/access_2026-{01..12}.log
# Beispielinhalt in 3 Logs einfügen
# (mehrfach echo mit >> hängt Zeilen an)
echo "2026-01-15 10:23:11 INFO User login: tim" >> logs/access_2026-01.log
echo "2026-01-15 10:25:34 WARN Slow query on /api/users" >> logs/access_2026-01.log
echo "2026-01-15 10:26:01 ERROR Database connection timeout" >> logs/access_2026-01.log
echo "2026-01-15 10:27:15 INFO Reconnected" >> logs/access_2026-01.log
echo "2026-01-15 11:02:44 ERROR 500 Internal Server Error" >> logs/access_2026-01.log
echo "2026-02-03 09:30:11 WARN Disk usage at 85%" >> logs/access_2026-02.log
echo "2026-02-03 14:22:17 ERROR Permission denied: /var/www/upload" >> logs/access_2026-02.log
echo "2026-03-12 08:00:00 INFO Daily backup started" >> logs/access_2026-03.log
echo "2026-03-12 16:45:01 WARN Memory usage high" >> logs/access_2026-03.log
- Liste alle
access_*.log-Dateien auf. - Zähle die Gesamtzahl der Zeilen aller
access_*.log-Dateien (wc -l). - Liste nur die Logs aus Q1 (Jan/Feb/Mär) auf — mit einer einzigen
ls-Zeile.
# 5)
ls logs/access_*.log
# 6) Gesamte Zeilenzahl aller access_*.log
wc -l logs/access_*.log
# 7) Nur Q1 (01, 02, 03)
ls logs/access_2026-0[123].log
- Suche in allen
access_*.lognach „ERROR" und speichere die Treffer inoutput/errors.txt. - Zähle, wie viele ERROR-Zeilen es gibt (
grep -cODER Pipe mitwc -l). - Filtere ALLE Warnings UND Errors heraus
(
grep -E "ERROR|WARN") →output/probleme.txt. - Versuche
cat /existiert_nicht.log 2> output/fehler.log— was steht inoutput/fehler.log?
# 8)
grep "ERROR" logs/access_*.log > output/errors.txt
# 9) zwei Varianten:
grep -c "ERROR" logs/access_*.log
# oder
grep "ERROR" logs/access_*.log | wc -l
# 10)
grep -E "ERROR|WARN" logs/access_*.log > output/probleme.txt
# 11)
cat /existiert_nicht.log 2> output/fehler.log
cat output/fehler.log
# → cat: /existiert_nicht.log: No such file or directory
- Schreibe einen Beispiel-Config-Inhalt in
configs/webserver.conf(10 Zeilen, davon 4 Kommentare mit#). - Erstelle eine „saubere" Config ohne Kommentare in
output/webserver_clean.conf(Hinweis:grep -v "^#"). - Bonus: Schreibe in einer Zeile sowohl auf
Bildschirm als auch in
output/audit-report.txt: „Audit-Vorbereitung abgeschlossen am 26.05.2026" — mittee.
# 12)
# webserver.conf mit echo aufbauen
# (erste Zeile mit > erstellt, alle weiteren mit >> anhängen)
echo "# HanovaTech Webserver Config" > configs/webserver.conf
echo "# Letztes Update: 2026-01-15" >> configs/webserver.conf
echo "listen 80" >> configs/webserver.conf
echo "server_name www.hanovatech.de" >> configs/webserver.conf
echo "# SSL muss noch aktiviert werden" >> configs/webserver.conf
echo "root /var/www/html" >> configs/webserver.conf
echo "index index.html" >> configs/webserver.conf
echo "# Logfile-Pfad" >> configs/webserver.conf
echo "access_log /var/log/nginx/access.log" >> configs/webserver.conf
echo "error_log /var/log/nginx/error.log" >> configs/webserver.conf
# 13)
grep -v "^#" configs/webserver.conf > output/webserver_clean.conf
# 14) Bonus
# Datum heute manuell einsetzen
# (Profi-Variante mit $(date) lernst du in Tag 3)
echo "Audit-Vorbereitung abgeschlossen am 26.05.2026" | tee output/audit-report.txt
Wenn ja: Du beherrschst jetzt Wildcards, Pipes, Redirection und
grep im Zusammenspiel — die wichtigste Shell-Kombi
überhaupt. Damit kannst du als Admin 80 % deiner täglichen
Routinen abkürzen.
Typische Anfänger-Fehler
Vorsicht> wichtige.txt statt >>Datei überschrieben statt erweitert. date > log.txt
leert das Log vor jedem Schreiben. Wenn dir der bisherige
Inhalt wichtig ist: immer >> benutzen.
ls *.txt in leerem OrdnerWenn nichts passt, wird * wörtlich übergeben — und
ls sucht dann nach einer Datei namens
„*.txt" und meldet
„No such file or directory". Das ist kein Bug, das ist
Globbing-Verhalten.
echo X >> /etc/hosts als normaler User scheitertsudo + Umleitung ist tricky: sudo echo X >> /etc/...
läuft das echo als root, aber die Umleitung macht
deine User-Shell — und die darf /etc/hosts nicht
anfassen. Lösung:
echo X | sudo tee -a /etc/hosts.
grep ohne Quotes bei Sonderzeichengrep error message file.log sucht „error" in den
Dateien message UND file.log — nicht
nach „error message" in einer Datei. Bei Leerzeichen oder
Sonderzeichen immer Quotes:
grep "error message" file.log.
grep Pattern mit *Verwechslung Wildcards vs. Regex. grep "*.txt"
sucht NICHT nach .txt-Endungen, sondern nach dem wörtlichen
Pattern *.txt — und in Regex hat * noch
dazu eine andere Bedeutung (0+ Wiederholung). Für „Datei endet auf
.txt": grep "\.txt$".
Kontrollfragen zum Kapitel
Selbst-Check- Wer löst Wildcards auf — die Shell oder der aufgerufene Befehl?
- Was bedeuten
*,?und[abc]? - Worin unterscheiden sich Wildcards und Brace Expansion?
- Welche Nummern haben stdin, stdout und stderr?
- Was ist der Unterschied zwischen
>und>>? - Wie leitest du nur Fehler in eine Datei um?
- Wie leitest du stdout UND stderr in dieselbe Datei? Nenne zwei Schreibweisen.
- Wozu ist
/dev/nullda? - Was macht
teeund wann brauchst du es? - Was macht
grep -vund wann ist das nützlich?
- Die Shell löst Wildcards auf, BEVOR der Befehl ausgeführt wird. Der Befehl sieht nur die fertige Liste.
*= beliebig viele Zeichen;?= genau ein Zeichen;[abc]= ein Zeichen aus der Liste.- Wildcards matchen existierende Dateien. Brace Expansion erzeugt Text-Listen, unabhängig von Existenz.
- stdin = 0, stdout = 1, stderr = 2.
>überschreibt die Zieldatei.>>hängt an.befehl 2> fehler.logbefehl &> datei(kurz) oderbefehl > datei 2>&1(klassisch).- „Mülltonne" — alles, was reingeht, ist weg. Praktisch zum
Verwerfen von Ausgabe oder Fehlern (z.B.
2>/dev/null). teeschreibt stdin gleichzeitig auf stdout UND in eine Datei. Klassisch fürs Loggen + Anzeigen, oder mitsudo teefür geschützte Dateien.grep -vzeigt Zeilen OHNE das Muster. Nützlich z.B. um Kommentare zu filtern:grep -v "^#" config.