- -P
- physischen Pfad mit aufgelösten Symlinks ausgeben
- -L
- logischen Pfad ausgeben, Symlinks bleiben (Standard)
pwdwo bin ich?
pwd -Pechter Pfad, wenn du über einen Symlink hierher gekommen bist
Linux-Befehle nach Aufgabe, von Dateien und Rechten bis zu Netzwerk, systemd und Textverarbeitung. Jeder Eintrag mit Optionen, kopierbaren Beispielen und macOS-Hinweisen.
Zuletzt geprüft: 2026-10-18, abgeglichen mit den Handbüchern zu GNU coreutils 9.x, util-linux, procps-ng, iproute2, systemd und bash 5.2; macOS-Hinweise anhand der Manpages von macOS 26.
Dateien lesen, durch Logs blättern, im Terminal bearbeiten und Versionen vergleichen.
cat /etc/os-releaseeine Datei ausgeben
cat part1.txt part2.txt > whole.txtzusammenfügen
cat -A script.sh | headversteckte Tabs und Windows-Zeilenenden ^M aufspüren
macOS/BSD: cat unter macOS hat kein -A; cat -vet liefert dieselbe Ansicht.
tac access.log | headneueste Logzeilen zuerst
macOS/BSD: Gibt es unter macOS nicht; nimm tail -r file.
less /var/log/syslogein Log lesen
journalctl -u nginx | less -Sbreite Zeilen ohne Umbruch
head -n 20 data.csvKopfzeile und erste Zeilen
head -c 512 file.bin | xxdeinen Blick auf den Anfang einer Binärdatei werfen
macOS/BSD: head unter macOS akzeptiert keine negativen Werte.
tail -n 50 app.logletzte 50 Zeilen
tail -F /var/log/nginx/access.logein rotiertes Log beobachten
tail -n +2 data.csvdie Kopfzeile einer CSV überspringen
sudo nano /etc/hostseine Systemdatei bearbeiten
Die Kürzelleiste unten am Bildschirm zeigt die Tasten; ^ steht für Ctrl und M- für Alt.
vim +42 app.pyin Zeile 42 öffnen
diff -u old.conf new.confgut lesbare Änderungsansicht
diff -rq dir1/ dir2/welche Dateien sich zwischen zwei Bäumen unterscheiden
diff <(sort a.txt) <(sort b.txt)nach dem Sortieren vergleichen, per Prozesssubstitution
make 2>&1 | tee build.logeinen Build beobachten und ein Log behalten
echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.confan eine Datei von root anhängen (sudo echo >> scheitert, weil die Shell die Umleitung ausführt)
printf '%s\n' "$var"eine Variable sicher ausgeben, selbst wenn sie mit -n beginnt
printf '%-12s %6.2f\n' disk 93.5ausgerichtete Spalten
echo -e und echo -n verhalten sich je nach Shell unterschiedlich; printf verhält sich überall gleich.
column -t -s, data.csv | less -Seine einfache CSV als Tabelle lesen
mount | column -tdurch Leerzeichen getrennte Ausgabe ausrichten
xxd image.png | headHex und ASCII nebeneinander
hexdump -C file.bin | headkanonischer Hexdump
xxd gehört zu den vim-Paketen; hexdump ist in util-linux (bei neueren Debian/Ubuntu in bsdextrautils).
strings -n 8 firmware.bin | lessVersionsangaben, URLs, Pfade finden
Unter Linux Teil von binutils.
Lesen und ändern, wer eine Datei lesen, schreiben und ausführen darf.
ls -l deploy.sh-rwxr-x--- 1 alice devs 812 Oct 18 09:12 deploy.sh
Das erste Zeichen ist der Typ (- Datei, d Verzeichnis, l Symlink). Dann drei Dreiergruppen: Besitzer, Gruppe, alle anderen. r=4, w=2, x=1, also ist rwxr-x--- gleich 750.
chmod 644 index.htmlBesitzer lesen/schreiben, alle lesen: normale Dateien
chmod 755 deploy.shBesitzer alles, andere lesen/ausführen: Skripte und Verzeichnisse
chmod 600 ~/.ssh/id_ed25519privater Schlüssel nur für dich lesbar; ssh lehnt lockerer geschützte Schlüssel ab
chmod +x script.shein Skript ausführbar machen
chmod go-w fileSchreibrecht für Gruppe und andere entfernen
chmod -R u=rwX,go=rX site/großes X setzt das Ausführrecht nur bei Verzeichnissen und Dateien, die es schon hatten
Symbolische und oktale Modi im chmod-Rechner zusammenstellen →
find site/ -type d -exec chmod 755 {} +die richtige Lösung, Teil 1: Verzeichnisse 755
find site/ -type f -exec chmod 644 {} +Teil 2: Dateien 644
Achtung: Gibt jedem Benutzer und jedem kompromittierten Dienst auf dem Rechner Schreibzugriff auf den ganzen Baum, macht alle Dateien ausführbar und lässt OpenSSH Schlüssel in einem ~/.ssh mit 777 ablehnen. Auf /etc oder /usr angewendet, kann es sudo und das System lahmlegen. Korrigier stattdessen den Besitz mit chown oder nutze die beiden find-Befehle.
sudo chown -R www-data:www-data /var/www/siteein Web-Root dem Webserver-Benutzer übergeben
sudo chown "$USER": file.txteine von root angelegte Datei übernehmen
Achtung: sudo chown -R auf /, /usr oder /etc löscht setuid-Bits und Besitzverhältnisse, auf die sudo, passwd und Dienste angewiesen sind; meist hilft dann nur eine Neuinstallation. Prüf den Pfad doppelt.
chgrp -R developers /srv/sharedeinen gemeinsamen Ordner einer Teamgruppe übergeben
umaskaktuelle Maske anzeigen, meist 0022
umask 077neue Dateien 600 und Verzeichnisse 700 in dieser Shell
Die Maske entfernt Bits: Dateien starten bei 666 und Verzeichnisse bei 777, 022 ergibt also 644 und 755.
sudo systemctl restart nginxein einzelner Admin-Befehl
sudo !!vorherigen Befehl mit sudo erneut ausführen
sudo -u postgres psqlals Dienstbenutzer ausführen
su - deployals deploy mit dessen Umgebung anmelden
sudo su -root-Shell, wenn root kein Passwort hat (sudo -i macht dasselbe)
setfacl -m u:alice:rw report.xlsxalice darf lesen und schreiben, ohne die Gruppe zu ändern
getfacl report.xlsxalle Einträge anzeigen
setfacl -R -m g:devs:rwX /srv/appeine Gruppe erhält Zugriff auf einen ganzen Baum
Ein + am Ende der Berechtigungsangabe von ls -l bedeutet, dass die Datei eine ACL hat.
sudo chattr +i /etc/resolv.confniemand, nicht einmal root, kann sie ändern oder löschen, bis -i gesetzt wird
lsattr /etc/resolv.confAttribute anzeigen; i bedeutet unveränderlich
Unterstützt auf ext4, XFS, Btrfs. Erscheint selbst als root „Operation not permitted“, prüf lsattr.
Herausfinden, was läuft, es stoppen und Dinge im Hintergrund ausführen.
ps aux | grep [n]ginxder [n]-Trick hält grep selbst aus den Ergebnissen heraus
ps aux --sort=-%mem | headgrößte Speicherverbraucher
ps -o pid,ppid,etime,cmd -p 1234wie lange ein Prozess schon läuft
macOS/BSD: ps unter macOS hat kein --sort; nimm ps aux -m (nach Speicher) oder ps aux -r (nach CPU).
pstree -pmit PIDs
pstree -p 1234was ein Prozess gestartet hat
top -b -n 1 | head -20Snapshot, den du in ein Ticket einfügen kannst
macOS/BSD: top unter macOS ist ein anderes Programm: sortieren mit top -o cpu oder top -o mem.
htop -u www-datanur die Prozesse eines Benutzers
Installieren mit apt install htop / dnf install htop.
pgrep -a nginxPIDs und Befehlszeilen
pgrep -f 'python manage.py runserver'ein Skript anhand seiner Argumente finden
macOS/BSD: Unter macOS bedeutet -a „Vorfahren einschließen“; nimm pgrep -lf, um Namen und Argumente zu sehen.
pkill -f "node server.js"eine Node-App stoppen
pkill -HUP nginxein Reload-Signal senden
pgrep -af nodevor dem Beenden prüfen, was -f treffen würde
Muster sind reguläre Ausdrücke, die irgendwo im Namen passen; pkill node trifft auch nodejs-helper. Vorher mit pgrep prüfen.
kill 1234höflich stoppen
kill -9 1234letzter Ausweg, wenn TERM ignoriert wird
kill %1Job 1 dieser Shell beenden
Versuch zuerst ein einfaches kill und gib ihm ein paar Sekunden: -9 überspringt das Aufräumen, sodass temporäre Dateien, Locks und halb geschriebene Daten zurückbleiben können.
killall firefoxalle Firefox-Prozesse
Unter Linux steckt das im Paket psmisc.
jobsJobs dieser Shell mit ihren Nummern auflisten
bg %1Job 1 im Hintergrund fortsetzen
fg %1wieder in den Vordergrund holen
Ctrl+Z hält das Vordergrundprogramm an (es läuft erst nach bg oder fg weiter).
./long-export.sh > export.log 2>&1 &starten und den Prompt zurückbekommen
waitim Skript auf das Ende der Hintergrundjobs warten
nohup ./server > server.log 2>&1 &übersteht das Schließen der SSH-Sitzung
Für alles Langlebige ist ein systemd-Dienst (siehe Dienste & Logs) oder tmux robuster.
disown -h %1nohup vergessen: mit bg in den Hintergrund schicken, dann disown
tmux new -s deployeine benannte Sitzung starten
tmux attach -t deploynach einem SSH-Abbruch wieder verbinden
Installation über deinen Paketmanager. GNU screen ist die ältere Alternative (Ctrl+A d zum Abkoppeln, screen -r zum Wiederverbinden).
nice -n 19 tar -czf backup.tgz /datahintergrundschonendes Backup
sudo renice -n -5 -p 1234Priorität eines laufenden Prozesses erhöhen
Der Nice-Wert reicht von -20 (höchste Priorität) bis 19 (niedrigste). Nur root darf unter 0 gehen.
timeout 30s curl -s https://example.com/healthnach 30 Sekunden aufgeben
timeout -s KILL 5m ./job.shnach fünf Minuten hart beenden
Endet mit Status 124, wenn das Zeitlimit erreicht wurde.
watch -n 2 df -hzusehen, wie der Speicherplatz vollläuft
watch -d 'ss -s'-d hebt Änderungen hervor
sudo lsof -i :8080was auf Port 8080 lauscht
sudo lsof +L1gelöschte, aber noch offene Dateien (Platte voll, aber du zeigt nichts)
lsof -p 1234alle Dateien, die ein Prozess offen hat
sudo fuser -vm /mnt/usbwarum umount „target is busy“ meldet
sudo fuser -v 8080/tcpProzess auf einem TCP-Port
Achtung: fuser -k beendet ohne Rückfrage jeden Prozess, der das Ziel nutzt; bei einem Mountpoint kann das auch deine eigene Shell sein.
time ./build.shreal = Echtzeit, user + sys = CPU-Zeit
strace -f -e trace=openat ./app 2>&1 | grep -v ENOENTwelche Dateien öffnet es tatsächlich?
sudo strace -p 1234woran hängt ein blockierter Prozess?
OS-Version, Kernel, CPU, Speicher, Hardware, Zeit und Last.
uname -rz. B. 6.8.0-45-generic
uname -mwelche Binärdatei du herunterladen musst: x86_64 oder aarch64
cat /etc/os-releaseNAME, VERSION_ID, ID für jede Distribution aus der systemd-Ära
lsb_release -aAlternative für Debian/Ubuntu, falls installiert
macOS/BSD: macOS: sw_vers.
hostnamectlHostname, OS, Kernel, Virtualisierung
sudo hostnamectl set-hostname web01den Rechner umbenennen
uptimeDurchschnittslast über 1, 5 und 15 Minuten
Die Last ist die Zahl der laufenden oder wartenden Prozesse. Vergleich sie mit der CPU-Anzahl (nproc): Eine Last von 4 auf 4 Kernen bedeutet volle Auslastung.
free -hauf die Spalte „available“ schauen, nicht auf „free“
macOS/BSD: macOS: vm_stat oder top -l 1 | grep PhysMem.
Linux nutzt freien RAM als Festplatten-Cache, daher sieht „free“ auf einem gesunden Rechner niedrig aus. „available“ ist das, was Programme noch bekommen können.
lscpuModell, Sockel, Kerne, Threads, Flags
make -j"$(nproc)"alle verfügbaren Kerne nutzen
macOS/BSD: macOS: sysctl -n hw.ncpu und sysctl -n machdep.cpu.brand_string.
lspci -k | grep -A3 -i vgaGrafikkarte und verwendeter Treiber
lsusbwird das USB-Gerät überhaupt erkannt?
sudo dmidecode -t memory | grep -i sizeinstallierter RAM pro Steckplatz
sudo lshw -shorteine Zeile pro Gerät
sudo dmesg -T | tail -30was gerade passiert ist (USB eingesteckt, Festplattenfehler)
sudo dmesg -T | grep -i 'out of memory'hat der OOM-Killer deine App gestoppt?
grep MemAvailable /proc/meminfoverfügbarer Speicher in kB
grep -c ^processor /proc/cpuinfoAnzahl logischer CPUs
cat /proc/1234/statusZustand und Speicher eines Prozesses
vmstat 1 5r = Run-Queue, si/so = Swapping, wa = Warten auf I/O
iostat -xz 1Auslastung (%util) und Latenz (await) pro Festplatte
iostat stammt aus dem Paket sysstat.
date '+%Y-%m-%d %H:%M:%S'Zeitstempel für Logs
date +%sSekunden seit 1970-01-01 UTC
date -d @1700000000Zeitstempel in Datum umwandeln (GNU)
date -d '2 days ago' +%Frelatives Datum (GNU)
macOS/BSD: date unter macOS hat kein -d. Nimm date -r 1700000000 für einen Zeitstempel, date -v-2d für „vor 2 Tagen“ und date -j -f '%Y-%m-%d' 2026-10-18 +%s zum Parsen.
timedatectlOrtszeit, UTC, Zeitzone, per NTP synchronisiert?
timedatectl list-timezones | grep Americaden Zonennamen finden
sudo timedatectl set-timezone America/TorontoZeitzone ändern
Freier Speicher, was ihn belegt, Partitionen, Einhängen und Formatieren.
df -halle eingehängten Dateisysteme
df -h .das Dateisystem, auf dem dieses Verzeichnis liegt
df -i„No space left“ trotz freier Bytes? Dann sind vielleicht die Inodes aus
macOS/BSD: Unter macOS filtert -T nach Typ, statt ihn anzuzeigen.
du -sh /var/logGröße eines Ordners
du -h -d 1 | sort -hUnterordner, größter zuletzt (funktioniert mit GNU und macOS)
sudo du -xh -d 1 / | sort -h | taildie größten Verzeichnisse auf oberster Ebene
macOS/BSD: du unter macOS hat -d, aber kein --max-depth.
sudo ncdu -x /mit den Pfeiltasten navigieren, d zum Löschen
Installieren mit apt install ncdu / dnf install ncdu.
lsblkFestplatten, Partitionen, Größen, Mountpoints
lsblk -fwelche Partition ext4/xfs ist, und ihre UUID
macOS/BSD: macOS: diskutil list.
sudo blkid /dev/sdb1UUID und TYPE, für /etc/fstab
findmntMount-Baum mit Optionen
findmnt -T /var/lib/dockerwelches Dateisystem diesen Pfad enthält
sudo findmnt --verify/etc/fstab vor dem Neustart auf Fehler prüfen
sudo mount /dev/sdb1 /mnt/usbeinen USB-Stick einhängen (das Verzeichnis muss existieren)
sudo mount -o remount,rw /ein schreibgeschütztes Root beschreibbar machen
sudo mount -t nfs nas:/export /mnt/naseine NFS-Freigabe einhängen
sudo umount /mnt/usbdanach kannst du sicher abstecken
sudo umount -l /mnt/naslazy: jetzt lösen, aufräumen, sobald nicht mehr belegt
„target is busy“ heißt, dass ein Prozess sie nutzt (oft deine eigene Shell, die in dem Verzeichnis steht): Finde ihn mit fuser -vm oder lsof.
UUID=3f6c... /data ext4 defaults,nofail 0 2eine Zeile pro Dateisystem; mit nofail bootet das System weiter, wenn die Platte fehlt
sudo mount -aalles aus der fstab jetzt einhängen: vor dem Neustart testen
Ein Tippfehler in der fstab kann den nächsten Bootvorgang im Notfallmodus enden lassen. Führ nach dem Bearbeiten immer sudo mount -a (oder findmnt --verify) aus.
sudo fdisk -lalle Festplatten und ihre Partitionen
sudo parted /dev/sdb printTyp der Partitionstabelle (gpt/msdos) und Aufteilung
Achtung: Das Schreiben einer Partitionstabelle (w in fdisk, mklabel in parted) macht vorhandene Daten auf dieser Platte unerreichbar. Prüf vorher den Gerätenamen mit lsblk; /dev/sda und /dev/sdb vertauschen sich leicht.
sudo mkfs.ext4 -L data /dev/sdb1ext4 mit Label
sudo mkfs.vfat -F 32 /dev/sdc1FAT32 für einen USB-Stick, den andere Geräte lesen können
Achtung: Löscht das Dateisystem auf dem Ziel sofort, ohne Rückfrage, wenn das Gerät nicht eingehängt ist. Prüf das Gerät mit lsblk -f; wer /dev/sda statt /dev/sda1 oder die falsche Platte formatiert, zerstört sie.
sudo fsck -f /dev/sdb1vollständige Prüfung einer ausgehängten Partition erzwingen
Achtung: Führ fsck nie auf einem mit Schreibzugriff eingehängten Dateisystem aus: Es kann es beschädigen. Erst aushängen, oder beim Root-Dateisystem von einem Rettungsmedium booten.
sudo dd if=ubuntu.iso of=/dev/sdX bs=4M status=progress conv=fsyncbootfähigen USB-Stick erstellen (sdX durch die ganze Platte ersetzen, keine Partition)
dd if=/dev/zero of=test.img bs=1M count=100eine 100-MB-Datei erstellen
Achtung: dd überschreibt das Ziel bei of= ohne Rückfrage. Vertauschst du if= und of= oder wählst das falsche /dev/sdX, wird diese Platte gelöscht. Prüf es direkt vor dem Ausführen mit lsblk.
macOS/BSD: macOS: Ziel ist /dev/rdiskN (aus diskutil list) nach diskutil unmountDisk, nimm bs=4m und drück Ctrl+T für den Fortschritt.
sync && sudo umount /mnt/usbbevor du ein USB-Laufwerk abziehst
swapon --showaktueller Swap
sudo fallocate -l 2G /swapfile && sudo chmod 600 /swapfile && sudo mkswap /swapfile && sudo swapon /swapfileeine 2-GB-Swap-Datei hinzufügen (in /etc/fstab eintragen, damit sie bleibt)
Unter Btrfs braucht eine Swap-Datei zusätzliche Schritte (btrfs filesystem mkswapfile bei aktuellen btrfs-progs).
shred -u -n 3 secrets.txtdreimal überschreiben, dann löschen
Achtung: Unumkehrbar. Außerdem nicht zuverlässig auf SSDs, Journaling- oder Copy-on-Write-Dateisystemen (Btrfs, ZFS) oder bei Snapshots; echten Schutz bietet Vollverschlüsselung.
IP-Adressen, Routen, offene Ports, HTTP-Anfragen, DNS, SSH und Dateiübertragung.
ip -br aeine Zeile pro Schnittstelle: Name, Status, Adressen
ip a show eth0eine Schnittstelle im Detail
hostname -Inur die IP-Adressen
macOS/BSD: macOS: ifconfig oder ipconfig getifaddr en0.
ip ersetzt das alte ifconfig (net-tools), das viele Distributionen nicht mehr installieren.
ip rRouten; „default via“ ist das Gateway
ip route get 1.1.1.1welche Schnittstelle und welches Gateway ein Ziel nutzt
sudo ip route add 10.20.0.0/16 via 192.168.1.1eine Route hinzufügen (geht beim Neustart verloren)
ip linkSchnittstellen und MAC-Adressen
sudo ip link set eth0 down && sudo ip link set eth0 upeine Schnittstelle neu starten
Achtung: Deaktivierst du die Schnittstelle, über die du per SSH verbunden bist, bricht deine Sitzung ab.
sudo ss -tulpnjeder lauschende Port und sein Programm
ss -tn state established '( dport = :443 )'bestehende Verbindungen zu Port 443
ss -sVerbindungssummen
macOS/BSD: macOS: lsof -iTCP -sTCP:LISTEN -n -P oder netstat -an.
ss ersetzt netstat; netstat -tulpn funktioniert noch, wo net-tools installiert ist.
curl -I https://example.comStatuszeile und Header
curl -LO https://example.com/file.tar.gzherunterladen und Weiterleitungen folgen
curl -s -o /dev/null -w '%{http_code}\n' https://example.comnur der Statuscode
curl -fsSL https://example.com/install.sh -o install.shein Skript herunterladen, um es vor dem Ausführen zu lesen
curl -H 'Content-Type: application/json' -d '{"name":"Ada"}' https://api.example.com/usersJSON per POST
curl -H "Authorization: Bearer $TOKEN" https://api.example.com/medoppelte Anführungszeichen, damit $TOKEN ersetzt wird
curl -X DELETE https://api.example.com/users/42andere Methoden
wget -c https://example.com/big.isonach Verbindungsabbruch fortsetzen
wget -qO- https://example.com/data.json | jq .direkt per Pipe an einen anderen Befehl
macOS/BSD: Nicht im Standard-macOS; nimm curl -LO (curl -C - -LO zum Fortsetzen).
dig +short example.comnur die A-Einträge
dig MX example.comMailserver
dig @1.1.1.1 example.comeinen bestimmten Resolver fragen (lokalen Cache umgehen)
dig -x 8.8.8.8Reverse-Lookup
dig +trace example.comder Delegation ab der Root folgen
Paketname: dnsutils (Debian/Ubuntu) oder bind-utils (Fedora/RHEL).
host example.comA, AAAA und MX in einer kurzen Antwort
nslookup example.com 8.8.8.8denselben Befehl gibt es unter Windows
resolvectl statusDNS-Server pro Schnittstelle
sudo resolvectl flush-cachesCache von systemd-resolved leeren
macOS/BSD: macOS: sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder.
Nur auf Systemen mit systemd-resolved (standardmäßig Ubuntu, Fedora).
ping -c 4 example.comvier Pakete, dann eine Zusammenfassung
Unter Linux und macOS läuft ping bis Ctrl+C, sofern du kein -c angibst (Windows hört nach 4 auf). Keine Antwort heißt nicht immer, dass er down ist: Viele Hosts blockieren ICMP.
traceroute -n example.comHops ohne DNS-Abfragen
tracepath example.comkein root nötig, meldet auch die MTU
macOS/BSD: macOS hat traceroute, aber kein tracepath.
traceroute muss unter Linux eventuell installiert werden; tracepath (iputils) ist meist vorhanden.
mtr -rw -c 100 example.comBericht nach 100 Proben pro Hop
Kombiniert ping und traceroute. Verlust nur an einem Hop in der Mitte liegt meist daran, dass dieser Router ICMP niedrig priorisiert; Verlust, der bis zum Ende anhält, ist echt.
ssh alice@203.0.113.10anmelden
ssh -p 2222 alice@hostabweichender Port
ssh alice@host 'df -h'einen Befehl ausführen und zurückkehren
ssh -J bastion.example.com alice@10.0.0.5über einen Bastion-Host springen
ssh -N -L 5432:localhost:5432 alice@db-hostdeinen lokalen DB-Client mit einem entfernten Postgres verbinden
ssh -N -D 1080 alice@hostüber den Server surfen
ssh-keygen -t ed25519 -C "you@example.com"neues Schlüsselpaar in ~/.ssh
ssh-copy-id alice@hostdeinen öffentlichen Schlüssel an die authorized_keys des Servers anhängen
ssh-keygen -R hostalten Host-Schlüssel nach Neuaufsetzen eines Servers entfernen („REMOTE HOST IDENTIFICATION HAS CHANGED“)
Host web
HostName 203.0.113.10
User deploy
Port 2222
IdentityFile ~/.ssh/id_ed25519dann einfach: ssh web (scp und rsync nutzen es auch)
scp report.pdf alice@host:/tmp/hochladen
scp alice@host:/var/log/app.log .herunterladen
scp -r -P 2222 site/ alice@host:~/einen Ordner über einen anderen Port hochladen
Seit OpenSSH 9.0 nutzt scp darunter das SFTP-Protokoll. Bei großen oder wiederholten Kopien ist rsync schneller, weil es nur Änderungen überträgt.
rsync -avzP site/ deploy@host:/srv/site/Schrägstrich am Ende von site/ kopiert den Inhalt, nicht den Ordner selbst
rsync -av --exclude 'node_modules' ./ /backup/app/lokales Backup ohne Ballast
macOS/BSD: Neuere macOS-Versionen liefern openrsync statt rsync aus; gängige Flags funktionieren, manche seltenere nicht.
src/ bedeutet „der Inhalt von src“; src ohne Schrägstrich bedeutet „der Ordner src“. Wer das verwechselt, verschachtelt Ordner (dest/src/…).
rsync -avn --delete site/ /srv/site/zuerst Probelauf: Zeilen mit „deleting“ zeigen, was wegfallen würde
rsync -av --delete site/ /srv/site/dann der echte Lauf
Achtung: Löscht alles im Ziel, was nicht in der Quelle ist. Vertauschte Quelle und Ziel oder ein leerer/falscher Quellpfad leeren das Ziel. Immer zuerst mit -n ausführen.
nc -zv db.internal 5432„succeeded“ oder „Connection refused“/Timeout
nc -l 9000auf einem Port lauschen, um eine Firewall von der anderen Seite zu testen
Die Flags unterscheiden sich zwischen netcat-Varianten: Die traditionelle braucht nc -l -p 9000.
sudo ufw status verboseRegeln und Standardrichtlinie
sudo ufw allow 22/tcpSSH erlauben (vor enable erledigen)
sudo ufw allow from 10.0.0.0/8 to any port 5432ein Port, ein Netz
Achtung: sudo ufw enable auf einem entfernten Server, ohne vorher SSH zu erlauben (ufw allow OpenSSH oder 22/tcp), sperrt dich aus.
sudo firewall-cmd --list-allaktive Zone und Regeln
sudo firewall-cmd --permanent --add-service=https && sudo firewall-cmd --reloadHTTPS dauerhaft öffnen
sudo firewall-cmd --permanent --add-port=8080/tcpeinen Port öffnen
Ohne --permanent gilt eine Regel nur bis zum nächsten Reload oder Neustart.
nmcli device statusSchnittstellen und ob sie verbunden sind
nmcli device wifi listNetze in der Nähe
nmcli device wifi connect 'MyWiFi' password 'secret'mit einem Netz verbinden
Dieselbe Aufgabe in den vier wichtigsten Paketmanagern: Debian/Ubuntu (apt), Fedora/RHEL (dnf), Arch (pacman), openSUSE (zypper). Stell allem, was das System verändert, sudo voran.
| Aufgabe | apt (Debian, Ubuntu) | dnf (Fedora, RHEL) | pacman (Arch) | zypper (openSUSE) |
|---|---|---|---|---|
| Paketlisten aktualisieren # dnf aktualisiert automatisch, wenn die Metadaten veraltet sind. Unter Arch nie pacman -Sy und danach -S pkg ausführen: Teil-Upgrades werden nicht unterstützt; nimm -Syu. | apt update | dnf makecache | pacman -Sy | zypper refresh |
| Alles aktualisieren # openSUSE Tumbleweed nutzt zypper dup. apt full-upgrade entfernt bei Bedarf auch Pakete, um das Upgrade abzuschließen. | apt update && apt upgrade | dnf upgrade | pacman -Syu | zypper update |
| Paket installieren # | apt install nginx | dnf install nginx | pacman -S nginx | zypper install nginx |
| Heruntergeladene Paketdatei installieren # Das ./ sagt apt, dass es eine Datei ist und kein Paketname, damit Abhängigkeiten aufgelöst werden (dpkg -i macht das nicht). | apt install ./app.deb | dnf install ./app.rpm | pacman -U app.pkg.tar.zst | zypper install ./app.rpm |
| Paket entfernen # | apt remove nginx | dnf remove nginx | pacman -R nginx | zypper remove nginx |
| Mit Konfigurationsdateien / ungenutzten Abhängigkeiten entfernen # | apt purge nginx && apt autoremove | dnf remove nginx && dnf autoremove | pacman -Rns nginx | zypper remove --clean-deps nginx |
| Nach einem Paket suchen # | apt search keyword | dnf search keyword | pacman -Ss keyword | zypper search keyword |
| Paketdetails anzeigen # | apt show nginx | dnf info nginx | pacman -Si nginx (installed: -Qi) | zypper info nginx |
| Installierte Pakete auflisten # | apt list --installed | dnf list --installed | pacman -Q | zypper search --installed-only |
| Verfügbare Updates auflisten # | apt list --upgradable | dnf check-update | checkupdates (pacman-contrib) | zypper list-updates |
| Zu welchem Paket eine Datei gehört # Für noch nicht installierte Dateien: dnf provides /path, apt-file search path (braucht apt-file), pacman -F path. | dpkg -S /usr/bin/curl | rpm -qf /usr/bin/curl | pacman -Qo /usr/bin/curl | rpm -qf /usr/bin/curl |
| Von einem Paket installierte Dateien auflisten # | dpkg -L nginx | rpm -ql nginx | pacman -Ql nginx | rpm -ql nginx |
| Paket auf der aktuellen Version halten # Unter DNF 4 braucht versionlock das Plugin-Paket versionlock. | apt-mark hold nginx | dnf versionlock add nginx | IgnorePkg = nginx in /etc/pacman.conf | zypper addlock nginx |
| Paket-Cache leeren # | apt clean | dnf clean all | pacman -Sc | zypper clean |
Wer du bist, wer angemeldet ist, und Konten verwalten.
iduid, gid und alle Gruppen, in denen du bist
id aliceein anderer Benutzer
wwer angemeldet ist und was er ausführt
last -n 10letzte Anmeldungen und Neustarts
sudo lastb -n 10letzte fehlgeschlagene Anmeldungen (Linux)
sudo useradd -m -s /bin/bash alice && sudo passwd aliceanlegen und Passwort setzen
Unter Debian/Ubuntu ist adduser alice der freundlichere interaktive Wrapper, der Home-Verzeichnis und Passwort einrichtet.
sudo usermod -aG docker alicealice darf docker ausführen
sudo usermod -aG sudo aliceAdmin unter Debian/Ubuntu (unter Fedora/RHEL/Arch heißt die Gruppe wheel)
Achtung: Ohne -a ersetzt usermod -G alle zusätzlichen Gruppen des Benutzers, was den sudo-Zugriff entfernen kann. Gruppenänderungen greifen bei der nächsten Anmeldung (oder führ newgrp docker aus).
sudo userdel -r olduserentfernt auch Home-Verzeichnis und Mail-Spool
Achtung: -r löscht das Home-Verzeichnis samt Dateien endgültig. Sichere es vorher oder sperre stattdessen das Konto (passwd -l).
passwddein eigenes ändern
sudo passwd alicedas eines anderen zurücksetzen
sudo passwd -l aliceAnmeldung per Passwort sperren (SSH-Schlüssel funktionieren eventuell weiter)
sudo groupadd developersneue Gruppe
sudo gpasswd -d alice developersalice daraus entfernen
groups alicedie Gruppen von alice
getent group sudoMitglieder von sudo (funktioniert auch mit LDAP)
getent passwd aliceKontoeintrag: UID, Home, Shell
sudo visudo -f /etc/sudoers.d/deployeigene Datei pro Regel
deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart myappein Befehl ohne Passwort
visudo prüft die Syntax vor dem Speichern. Wer /etc/sudoers mit einem normalen Editor bearbeitet und sich vertippt, kann alle von sudo aussperren.
sudo chage -l aliceletzte Änderung und Ablaufdaten
sudo chage -M 90 alicealle 90 Tage ablaufen lassen
tar, gzip, xz, zip und Prüfsummen.
tar -czf site-2026-10-18.tar.gz site/gzip-komprimiertes Archiv eines Ordners
tar -cJf logs.tar.xz --exclude='*.tmp' logs/kleineres xz-Archiv ohne temporäre Dateien
tar -xf archive.tar.gzGNU tar und macOS-tar erkennen die Komprimierung selbst
tar -xzf app.tar.gz -C /opt/app --strip-components=1in einen Ordner, ohne das umschließende Verzeichnis
tar -tf backup.tar.gz | lessInhalt ansehen, ohne zu entpacken
tar -xf backup.tar.gz etc/nginx/nginx.confeine Datei herausholen (Pfad wie von -t angezeigt)
tar --zstd -cf data.tar.zst data/viel schneller als xz, Verhältnis ähnlich wie gzip -9 oder besser
zstd -d file.zsteine einzelne Datei entpacken
Braucht GNU tar 1.31+ (oder ein aktuelles bsdtar) und das Programm zstd.
gzip -k access.logerzeugt access.log.gz und behält das Original
zcat access.log.gz | grep 404lesen, ohne auf die Platte zu entpacken
zgrep 500 access.log.*.gzrotierte Logs direkt durchsuchen
Ohne -k ersetzt gzip die Datei durch die .gz-Version.
xz -T0 -k big.sqlalle CPU-Kerne, Original behalten
unxz big.sql.xzentpacken
zip -r site.zip site/einen Ordner zippen
zip -r site.zip site/ -x '*.git*' '*/node_modules/*'Pfade ausschließen
zip -e verschlüsselt mit dem veralteten ZipCrypto-Verfahren, das schwach ist. Für echte Geheimhaltung nimm 7z oder gpg.
unzip files.zip -d files/in einen Ordner
unzip -l files.zipnur den Inhalt auflisten
unzip -o files.zipohne Rückfrage überschreiben
7z x archive.7zmit vollständigen Pfaden entpacken
7z a -p backup.7z docs/AES-256-verschlüsseltes Archiv (fragt nach einem Passwort)
7z l archive.rarInhalt vieler Formate auflisten
Paket: p7zip-full / 7zip unter Debian/Ubuntu, p7zip oder 7zip unter Fedora/Arch.
sha256sum ubuntu.isomit dem Hash auf der Downloadseite vergleichen
sha256sum -c SHA256SUMS --ignore-missingjede aufgeführte Datei prüfen, die du tatsächlich hast
macOS/BSD: macOS: shasum -a 256 file (und shasum -a 256 -c SUMSFILE).
split -b 100M backup.tar.gz backup.part.backup.part.aa, .ab, …
cat backup.part.* > backup.tar.gzwieder zusammenfügen
Dateien nach Name, Alter oder Größe finden und Text in Dateien suchen.
find . -name '*.log'Muster in Anführungszeichen setzen, damit die Shell es nicht vorher erweitert
find / -iname 'nginx.conf' 2>/dev/nullüberall suchen, Berechtigungsfehler ausblenden
find . -maxdepth 1 -type ddirekte Unterverzeichnisse
find . -type l -xtype ldefekte Symlinks (GNU)
find . -type f -emptyleere Dateien
find /var/log -type f -mtime +30Logs, die älter als 30 Tage sind
find . -type f -mmin -15was sich in den letzten 15 Minuten geändert hat
sudo find / -xdev -type f -size +500M -exec ls -lh {} + 2>/dev/nullDateien über 500 MB im Root-Dateisystem
find . -name '*.sh' -exec chmod +x {} +{} + übergibt viele Dateien pro Befehl (schnell)
find . -name '*.py' -exec grep -l 'TODO' {} +welche Python-Dateien TODO enthalten
find . -name '*.jpg' -print0 | xargs -0 -P4 -n 20 jpegoptimparallele Verarbeitung, sicher bei Leerzeichen in Namen
find /tmp/app -name '*.tmp' -mtime +7 -printSchritt 1: auflisten, was passt
find /tmp/app -name '*.tmp' -mtime +7 -deleteSchritt 2: derselbe Befehl mit -delete am Ende
Achtung: Die Reihenfolge zählt: -delete wirkt dort, wo es steht, also löscht find . -delete -name "*.tmp" alles unter ., bevor der Namenstest überhaupt greift. Setz -delete ans Ende und führ zuerst -print aus.
find /srv -type f -perm -o+wfür alle beschreibbare Dateien
sudo find / -xdev -perm -4000 -type f 2>/dev/nullsetuid-Programme
locate -i nginx.confviel schneller als find /
sudo updatedbIndex jetzt aktualisieren
Bereitgestellt von plocate oder mlocate; der Index wird täglich neu erstellt, heute angelegte Dateien fehlen also eventuell, bis updatedb läuft.
grep -n 'ERROR' app.logpassende Zeilen mit Nummern
grep -v '^#' nginx.conf | grep -v '^$'Konfiguration ohne Kommentare und Leerzeilen
grep -c 'Failed password' /var/log/auth.logfehlgeschlagene SSH-Anmeldungen zählen
grep -rn 'TODO' src/jedes TODO mit Datei und Zeile
grep -rl --include='*.php' 'mysql_connect' .welche PHP-Dateien noch eine alte API nutzen
grep -rn --exclude-dir={.git,node_modules} 'apiKey' .Ordner mit viel Rauschen überspringen
grep -C 3 'Traceback' app.log3 Zeilen davor und danach
grep -A 20 'Exception' app.logder Stacktrace nach dem Fehler
grep -E 'error|warn' app.logeines der Wörter (erweiterter regulärer Ausdruck)
grep -Eo '[0-9]{1,3}(\.[0-9]{1,3}){3}' access.log | sort | uniq -c | sort -rn | headhäufigste IP-Adressen in einem Log
grep -P '\d{4}-\d{2}-\d{2}' file\d im Perl-Stil (GNU grep)
macOS/BSD: -E funktioniert überall; -P (PCRE) ist eine GNU-Funktion und nicht in jeder macOS-Version verfügbar.
type llsagt dir, ob es ein Alias, eine Funktion, ein Builtin oder eine Datei ist
command -v docker >/dev/null || echo "docker missing"portable Prüfung in Skripten
which -a python3jedes python3 im PATH, in Reihenfolge
Text und JSON zerschneiden, filtern, sortieren, zählen, umwandeln und umformen.
sed 's/http:/https:/g' links.txtErgebnis ausgeben; die Datei bleibt unverändert
sed 's|/usr/local|/opt|g' paths.txtbeliebiges Trennzeichen, praktisch für Pfade
sed -E 's/([0-9]+)px/\1rem/g' style.csseine erfasste Gruppe wiederverwenden
sed -i 's/^#Port 22/Port 2222/' /etc/ssh/sshd_configGNU sed
sed -i.bak 's/foo/bar/g' config.inibehält config.ini.bak; funktioniert mit GNU und macOS
macOS/BSD: sed unter macOS verlangt ein Argument nach -i: sed -i '' 's/foo/bar/g' file. GNU sed liest '' als Skript, die einzige Form, die in beiden funktioniert, ist also -i.bak.
sed -n '100,120p' big.logZeilen 100 bis 120
sed '/^\s*#/d; /^$/d' app.confKommentare und Leerzeilen entfernen (GNU \s)
sed -n '/BEGIN CERT/,/END CERT/p' bundle.pemalles zwischen zwei Markierungen
awk '{print $1}' access.logerste Spalte (Client-IP)
awk -F: '{print $1, $7}' /etc/passwdBenutzer und Shell
awk -F, 'NR>1 {print $2}' data.csvzweite CSV-Spalte, Kopfzeile überspringen (nur einfache CSV: keine Kommas in Anführungszeichen)
awk '$9 >= 500' access.logZeilen, in denen Feld 9 (Status) 5xx ist
awk '{s += $2} END {print s}' sales.txtSumme von Spalte 2
awk '{c[$1]++} END {for (k in c) print c[k], k}' access.log | sort -rn | headAnzahl pro Wert, Top 10
cut -d, -f1,3 data.csvSpalten 1 und 3
cut -d: -f1 /etc/passwdalle Benutzernamen
cut -c1-10 filedie ersten 10 Zeichen jeder Zeile
cut behandelt jedes Trennzeichen als Feldgrenze, zwei Leerzeichen ergeben also ein leeres Feld. Für mit Leerzeichen ausgerichtete Ausgabe nimm awk.
du -sh * | sort -hOrdner nach Größe
sort -t, -k3,3nr data.csvCSV nach Spalte 3, numerisch, absteigend
sort -u emails.txt > unique.txtsortiert und ohne Duplikate
sort ips.txt | uniq -c | sort -rn | headdie 10 häufigsten Zeilen
uniq fasst nur aufeinanderfolgende Duplikate zusammen, also vorher sortieren.
wc -l access.logAnzahl der Zeilen
ls | wc -lwie viele Einträge dieser Ordner hat
grep -c '' fileZeilenzahl, die auch eine letzte Zeile ohne Zeilenumbruch mitzählt
tr 'a-z' 'A-Z' < in.txtin Großbuchstaben
tr -d '\r' < windows.txt > unix.txtWindows-Zeilenenden (CRLF) entfernen
tr -s ' ' < filewiederholte Leerzeichen zusammenfassen
tr '\n' ',' < list.txtZeilen mit Kommas verbinden
tr liest nur die Standardeingabe, leite die Datei also mit < hinein.
find . -name '*.log' -print0 | xargs -0 rm -fgefundene Dateien sicher löschen
cat urls.txt | xargs -n 1 -P 4 curl -sO4 gleichzeitig herunterladen
ls *.png | xargs -I {} cp {} /backup/{}ein Befehl pro Element
macOS/BSD: GNU xargs führt den Befehl auch bei leerer Eingabe einmal aus, außer du gibst -r an; xargs unter macOS überspringt leere Eingaben standardmäßig und akzeptiert -r aus Kompatibilitätsgründen.
jq . response.jsonschön formatiert ausgeben
jq -r '.items[].name' data.jsonein Name pro Zeile
jq -r '.[] | select(.active) | .email' users.jsonfiltern, dann ein Feld auswählen
curl -s https://api.github.com/repos/jqlang/jq | jq '.stargazers_count'direkt aus einer API
Installieren mit apt/dnf install jq. Bei aktuellem macOS dabei.
paste -sd, ids.txtalle Zeilen mit Kommas verbunden
paste names.txt emails.txtzwei Dateien als zwei Spalten
comm -12 <(sort a.txt) <(sort b.txt)in beiden
comm -23 <(sort a.txt) <(sort b.txt)nur in a.txt
seq 1 51 bis 5, eine pro Zeile
seq -w 1 10mit führenden Nullen: 01 … 10
for i in $(seq 1 3); do echo "run $i"; doneSchleifenzähler
printf '%s' 'user:pass' | base64kodieren (printf vermeidet einen abschließenden Zeilenumbruch)
echo dXNlcjpwYXNz | base64 -ddekodieren
base64 -w 0 image.png > image.b64ohne Zeilenumbruch (GNU bricht nach 76 Zeichen um)
macOS/BSD: base64 unter macOS bricht standardmäßig nicht um und hat kein -w. Zum Dekodieren -d verwenden (ältere macOS-Versionen nutzten -D).
iconv -f WINDOWS-1252 -t UTF-8 old.csv > new.csvZeichensalat aus Excel-Exporten beheben
iconv -lunterstützte Kodierungen auflisten
shuf -n 1 names.txteine zufällige Zeile
shuf -i 1-100 -n 5fünf Zufallszahlen von 1 bis 100
systemd-Dienste: starten, stoppen, beim Booten aktivieren und ihre Logs mit journalctl lesen.
systemctl status nginxZustand, PID, Speicher und die letzten Logzeilen
systemctl is-active --quiet nginx && echo upfür Skripte
sudo systemctl restart nginxvollständiger Neustart
sudo systemctl reload nginxKonfiguration neu einlesen, ohne Verbindungen zu trennen (sofern der Dienst das unterstützt)
Teste die Konfiguration nach Möglichkeit vor dem Neustart, z. B. mit sudo nginx -t, damit ein Tippfehler die Website nicht lahmlegt.
sudo systemctl enable --now dockerbeim Booten aktivieren und jetzt starten
sudo systemctl disable --now cupsjetzt und beim Booten stoppen
sudo systemctl mask bluetoothdas Starten komplett verhindern (unmask macht es rückgängig)
systemctl --failedwas kaputt ist
systemctl list-units --type=service --state=runningwas läuft
systemctl list-unit-files --state=enabledwas beim Booten startet
sudo systemctl edit nginxDrop-in-Override, das Paket-Upgrades übersteht
systemctl cat nginxdie Unit samt allen Overrides
sudo systemctl daemon-reloadnötig, nachdem Unit-Dateien von Hand bearbeitet wurden
[Unit]
Description=My app
After=network.target
[Service]
User=app
WorkingDirectory=/srv/app
ExecStart=/srv/app/bin/server
Restart=on-failure
[Install]
WantedBy=multi-user.targetdanach: sudo systemctl daemon-reload && sudo systemctl enable --now myapp
journalctl -u nginx -feinem Dienst folgen
journalctl -u myapp --since '10 min ago'jüngster Zeitraum
journalctl -b -1 -p errFehler aus dem Bootvorgang vor dem Absturz
journalctl --disk-usagewie viel Platz die Logs belegen
sudo journalctl --vacuum-size=500Mhöchstens 500 MB archivierte Logs behalten
sudo journalctl --vacuum-time=14darchivierte Logs löschen, die älter als zwei Wochen sind
Für ein dauerhaftes Limit SystemMaxUse= in /etc/systemd/journald.conf setzen.
sudo tail -f /var/log/syslogallgemeines Log unter Debian/Ubuntu (/var/log/messages unter Fedora/RHEL)
sudo tail -f /var/log/auth.logAnmeldungen und sudo unter Debian/Ubuntu (/var/log/secure unter RHEL)
Manche Distributionen (Fedora, Arch) speichern Logs nur im Journal, sofern rsyslog nicht installiert ist.
sudo rebootsofort neu starten
sudo shutdown -r +10 'Kernel update'in 10 Minuten neu starten und angemeldete Benutzer warnen
sudo shutdown -cgeplantes Herunterfahren abbrechen
sudo shutdown -h nowausschalten
Befehle nach Zeitplan oder einmalig später ausführen.
crontab -edeine Crontab in $EDITOR öffnen
crontab -lsie auflisten
crontab -l > crontab.baksie sichern
Den Zeitplan im Cron-Generator erstellen und erklären lassen →
30 2 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1täglich um 02:30, Ausgabe behalten
*/15 * * * * /usr/local/bin/check.shalle 15 Minuten
0 9 * * 1-5 /usr/local/bin/report.sh09:00 Montag bis Freitag
@reboot /usr/local/bin/startup.sheinmal beim Booten
Cron läuft mit minimalem PATH und ohne Shell-Profil: Nutze absolute Pfade. Ein % im Befehl muss als \% escapt werden.
crontab -l > ~/crontab.bak && crontab -rvor dem Entfernen sichern
crontab ~/crontab.bakaus einer Datei wiederherstellen
Achtung: Löscht ohne Rückfrage alle deine Cron-Jobs, und r liegt auf der Tastatur direkt neben e. Manche Cron-Implementierungen bieten -i, um vorher zu fragen (crontab -ri).
0 3 * * * root /usr/local/bin/cleanup.shZeile in /etc/cron.d/cleanup: Achtung, zusätzliches Benutzerfeld
ls /etc/cron.daily/Skripte, die run-parts einmal täglich ausführt
Unter Debian und Ubuntu werden Dateien in /etc/cron.d ignoriert, deren Namen einen Punkt enthalten; nenn sie also backup, nicht backup.cron.
echo 'systemctl restart myapp' | sudo at 02:00heute Nacht um 2 Uhr
echo './report.sh' | at now + 30 minutesin einer halben Stunde
atqausstehende Jobs
atrm 3Job 3 abbrechen
Braucht das Paket at und einen laufenden atd-Dienst.
systemctl list-timersalle Timer und wann sie das nächste Mal auslösen
[Timer]
OnCalendar=*-*-* 02:30:00
Persistent=true
[Install]
WantedBy=timers.targetbackup.timer neben backup.service; Persistent holt nach Ausfallzeiten nach
systemd-analyze calendar 'Mon..Fri 09:00'prüfen, was ein OnCalendar-Ausdruck bedeutet
sleep 5 && curl -s localhost:8080/healtheinem Dienst Zeit zum Starten geben
sleep 2mSuffixe funktionieren mit GNU und aktuellem macOS
Pipes, Umleitungen, Globbing, Variablen, Verlauf und die Tasten, die am meisten Zeit sparen. macOS nutzt standardmäßig zsh: Fast alles hier funktioniert auch dort, außer shopt, help und Funktionen von bash 4 (macOS liefert bash 3.2 aus).
ps aux | grep nginxeine Liste filtern
history | grep 'docker run'einen früher ausgeführten Befehl finden
set -o pipefailin Skripten: Eine Pipeline schlägt fehl, wenn irgendein Teil fehlschlägt, nicht nur der letzte
ls -l > listing.txtüberschreiben (legt die Datei an)
echo 'done' >> progress.loganhängen
set -o noclobber> verweigert das Überschreiben vorhandener Dateien (>| erzwingt es)
Die Shell leert die Datei, bevor der Befehl läuft, daher bleibt bei sort file > file eine leere Datei übrig. Schreib in einen neuen Namen und dann mv.
find / -name x 2>/dev/nullFehlermeldungen verwerfen
./build.sh > build.log 2>&1Ausgabe und Fehler in einer Datei (Reihenfolge zählt: erst >, dann 2>&1)
./build.sh &> build.logbash-Kurzform dafür
mysql mydb < dump.sqlDatei als Eingabe
cat > config.yml <<'EOF'
port: 8080
host: $HOST stays literal
EOF'EOF' in Anführungszeichen verhindert, dass $Variablen ersetzt werden
grep -c a <<< "banana"Here-String
make && sudo make installnur installieren, wenn der Build erfolgreich war
cd /srv/app || exit 1ein Skript stoppen, wenn cd fehlschlägt
(cd frontend && npm run build)Klammern: eine Subshell, dein Verzeichnis ändert sich also nicht
echo "Today is $(date +%A)"Befehlssubstitution
echo $(( 1024 * 4 ))Ganzzahlarithmetik
diff <(ls dir1) <(ls dir2)Prozesssubstitution: Ausgabe als temporäre Datei
Backticks `command` sind die alte Form von $(command); $( ) lässt sich verschachteln und liest sich besser.
ls *.jpgalle JPGs in diesem Ordner
rm photo-??.pngphoto-01.png … photo-99.png
cp config.{yml,yml.bak}Klammererweiterung: cp config.yml config.yml.bak
shopt -s globstar; ls **/*.md** passt in beliebiger Tiefe (bash 4+)
Globs erfassen standardmäßig keine Punktdateien (shopt -s dotglob ändert das). Passt nichts, übergibt bash das Muster wörtlich, außer shopt -s nullglob ist gesetzt.
echo 'Cost: $5'einfache Anführungszeichen: nichts wird ersetzt
echo "Home is $HOME"doppelte Anführungszeichen: Variablen werden ersetzt, Leerzeichen bleiben
cp "$file" "$dest/"Variablen mit Pfaden immer in Anführungszeichen setzen: Leerzeichen machen sie sonst kaputt
name="Ada"; echo "Hi $name"setzen und nutzen
echo "${PORT:-8080}"Standardwert, wenn nicht gesetzt oder leer
file=report.tar.gz; echo "${file%%.*}" "${file##*/}"Endung entfernen / Verzeichnis entfernen
echo "${#name}"Länge des Strings
export NODE_ENV=productionfür jedes aus dieser Shell gestartete Programm sichtbar
DEBUG=1 ./appnur für diesen einen Befehl
printenv | sortsie auflisten
unset DEBUGentfernen
Gehen verloren, wenn die Shell beendet wird. Leg exports in ~/.bashrc (interaktive Shells) oder ~/.profile (Login-Shells) ab, damit sie bleiben.
echo "$PATH" | tr : '\n'ein Eintrag pro Zeile
export PATH="$HOME/.local/bin:$PATH"deinen eigenen bin-Ordner voranstellen (in ~/.bashrc eintragen)
hash -rzwischengespeicherte Befehlspfade vergessen, nachdem Binärdateien verschoben wurden
alias ll='ls -alF'in ~/.bashrc eintragen, damit er bleibt
source ~/.bashrcÄnderungen übernehmen, ohne ein neues Terminal zu öffnen (wie . ~/.bashrc)
\lsdas echte ls ausführen und einen Alias umgehen
grep -q root /etc/passwd; echo $?0 gefunden, 1 nicht gefunden, 2 Fehler
set -euo pipefailam Anfang eines Skripts: bei Fehlern, nicht gesetzten Variablen und fehlgeschlagenen Pipes abbrechen
sudo !!letzten Befehl mit sudo erneut ausführen
cd !$das letzte Argument des vorherigen Befehls verwenden
!42Zeile 42 des Verlaufs erneut ausführen
^foo^barletzten Befehl mit bar statt foo erneut ausführen
Mit HISTCONTROL=ignorespace (unter Ubuntu als Teil von ignoreboth Standard) wird ein Befehl mit führendem Leerzeichen nicht gespeichert: nützlich für Befehle mit Geheimnissen.
bind -P | lessalle Tastenbelegungen auflisten
man rsyncvollständiges Handbuch; / zum Suchen, q zum Beenden
man 5 crontabAbschnitt 5: das Dateiformat, nicht der Befehl
help cdbash-Builtins haben keine eigene Manpage
apropos partitionwelche Befehle ein Wort erwähnen
#!/usr/bin/env bash
set -euo pipefail
name="${1:-world}"
if [[ -f "$name.txt" ]]; then
echo "found $name.txt"
fi
for f in *.log; do
echo "$f"
doneArgumente, ein Test, eine Schleife
chmod +x script.sh && ./script.sh Adaausführbar machen und starten
bash -x script.shjede Zeile beim Ausführen protokollieren
$1 … $9 sind Argumente, "$@" sind alle, $# ist ihre Anzahl. [[ ]] ist bash; in POSIX-sh-Skripten [ ] verwenden.
resetwenn cat auf eine Binärdatei das Terminal nur noch Zeichensalat ausgeben lässt
Ein Problem gefunden oder etwas, das besser sein könnte? Wir lesen jede Nachricht und beheben Fehler schnell.
Dieser Linux-Spickzettel gruppiert mehr als 200 Befehle nach der Aufgabe, die du erledigen willst: Navigieren und Dateien verwalten, Rechte, Prozesse, Speicherplatz, Netzwerk, Pakete, Benutzer, Archive, Suchen, Textverarbeitung, systemd-Dienste und Logs, cron und die Bash-Grundlagen, die alles verbinden. Jeder Eintrag zeigt die Syntax, die Optionen, die du tatsächlich brauchst, mit einer einzeiligen Erklärung, kopierbare Beispiele und, wo es darauf ankommt, eine Warnung. Suche nach Aufgabe („free disk space“, „what is using port 8080“) oder nach Befehlsname und verlinke direkt auf jeden Eintrag.
Die Optionen folgen den Handbüchern von GNU coreutils, util-linux, procps-ng, iproute2, systemd und bash – also dem, was Ubuntu, Debian, Fedora, RHEL, Arch und openSUSE mitliefern. Wo sich macOS anders verhält, sagt ein blauer Hinweis wie, denn sed -i, date -d, stat -c und xargs sind die klassischen Stellen, an denen ein Skript, das auf dem einen System geschrieben wurde, auf dem anderen scheitert. Es ist eine Referenz für die gängigen 90 %, kein Ersatz für Manpages: Für selten genutzte Optionen bleibt man <command> maßgeblich.
Fang mit Navigation und Dateien an: pwd, ls, cd, mkdir, cp, mv, rm, cat und less. Dann man (Hilfe), sudo, grep und find zum Suchen, chmod und chown für Rechte, ps, top und kill für Prozesse, df und du für Speicherplatz sowie ssh und scp für entfernte Rechner. Lerne Pipes (|) und Umleitungen (> und >>) früh, denn mit ihnen kombinierst du alles andere.
Führe df -h aus, um den freien Platz auf jedem eingehängten Dateisystem in gut lesbaren Einheiten zu sehen. Um herauszufinden, was den Platz belegt, führe in einem Verzeichnis du -h -d 1 | sort -h aus: Es listet die Unterordner auf, die größten zuletzt. Meldet df eine volle Platte, du findet aber nichts, hält wahrscheinlich ein Prozess eine gelöschte Datei noch offen; sudo lsof +L1 listet solche Dateien auf.
Führe sudo ss -tulpn aus, um jeden lauschenden TCP- und UDP-Port mit dem zugehörigen Programm aufzulisten, oder sudo lsof -i :8080 für einen einzelnen Port. Das sudo ist wichtig: Ohne siehst du nur die Namen deiner eigenen Prozesse. ss hat netstat abgelöst, das auf Systemen mit installiertem net-tools-Paket weiterhin funktioniert.
kill PID sendet SIGTERM, das den Prozess bittet, sich zu beenden, und ihn aufräumen lässt: Dateien schreiben, Sperren freigeben, Verbindungen schließen. kill -9 PID sendet SIGKILL, das der Kernel sofort durchsetzt und das der Prozess weder abfangen noch ignorieren kann – aufgeräumt wird also nicht. Nimm zuerst ein einfaches kill, warte ein paar Sekunden und heb dir -9 für Prozesse auf, die es ignorieren.
macOS liefert BSD-sed mit, bei dem -i ein Argument für die Backup-Endung verlangt. Auf macOS schreibst du sed -i '' 's/old/new/g' file; unter Linux mit GNU-sed scheitert derselbe Befehl, weil '' als Skript gelesen wird. Die Form, die auf beiden funktioniert, ist sed -i.bak 's/old/new/g' file – sie behält eine Sicherungskopie, die du danach löschen kannst.
Fast alle: Die Kernwerkzeuge stammen überall aus denselben GNU- und util-linux-Projekten. Unterschiedlich sind der Paketmanager (apt bei Debian und Ubuntu, dnf bei Fedora und RHEL, pacman bei Arch, zypper bei openSUSE, nebeneinander in der Pakettabelle), manche Pfade zu Logdateien, die Admin-Gruppe (sudo vs. wheel) und das Firewall-Frontend (ufw vs. firewalld). Alpine und BusyBox-basierte Systeme nutzen kleinere Versionen der Tools mit weniger Optionen.
Eine kurze Liste von Befehlen richtet fast den gesamten Schaden an: rm -rf mit falschem oder leerem Pfad, dd oder mkfs auf der falschen Platte, chmod -R 777 oder chown -R auf einem Systemverzeichnis, rsync --delete oder Spiegelungen im robocopy-Stil mit vertauschter Quelle und Ziel, crontab -r statt crontab -e, usermod -G ohne -a und find mit -delete an der falschen Stelle. Jeder davon ist im Spickzettel als gefährlich markiert, samt der konkreten Art, wie es schiefgeht.
Die Gewohnheit, die das meiste verhindert: zuerst die harmlose Variante ausführen. Vor rm -rf führst du ls auf denselben Pfad aus. Vor find … -delete dasselbe find mit -print. Vor rsync --delete fügst du -n für einen Probelauf hinzu. Vor dd oder mkfs führst du lsblk aus und liest den Gerätenamen zweimal. Schreib in Skripten ${DIR:?} statt $DIR, damit eine leere Variable das Skript abbricht, statt einen Pfad in / zu verwandeln.
Zwei Shell-Einstellungen helfen ebenfalls: set -euo pipefail am Anfang eines Skripts stoppt beim ersten Fehler, statt mit kaputtem Zustand weiterzumachen, und set -o noclobber sorgt dafür, dass > eine vorhandene Datei nicht überschreibt.
macOS ist Unix, aber seine Kommandozeilen-Tools stammen von FreeBSD statt von GNU, und die Unterschiede zeigen sich genau dann, wenn du einen Befehl aus einem Linux-Tutorial kopierst:
• sed -i braucht auf macOS ein Argument (sed -i '' …); -i.bak funktioniert auf beiden.
• date hat auf macOS kein -d; nimm date -r <epoch>, um einen Zeitstempel umzuwandeln, und date -v-2d für relative Daten.
• stat verwendet -f mit anderen Formatbuchstaben statt GNU -c.
• xargs überspringt auf macOS standardmäßig leere Eingaben, während GNU-xargs den Befehl einmal ausführt, sofern nicht -r angegeben ist.
• du akzeptiert auf beiden -d 1, aber nur GNU kennt --max-depth; ps hat auf macOS kein --sort (nimm ps aux -m oder -r).
• head -n -5, tac, free, ip, ss, timeout und watch fehlen in einem Standard-macOS.
Wenn du auf einem Mac GNU-Verhalten brauchst, installieren die Homebrew-Pakete coreutils, gnu-sed und findutils die GNU-Versionen mit dem Präfix g (gsed, gdate, gstat, gxargs).
ls -l zeigt Rechte als zehn Zeichen an, etwa -rwxr-x---. Das erste ist der Typ (- Datei, d Verzeichnis, l Link); die nächsten neun sind drei Gruppen aus Lesen, Schreiben und Ausführen für den Besitzer, die Gruppe und alle anderen. Als Zahlen ist r 4, w 2 und x 1, pro Gruppe addiert – rwxr-x--- ist also 750.
Typische Modi: 644 für normale Dateien, 755 für Verzeichnisse und Skripte, 600 für private Schlüssel und Dateien mit Geheimnissen, 700 für ein privates Verzeichnis wie ~/.ssh. Bei einem Verzeichnis bedeutet x „darf betreten werden“ – deshalb brauchen Verzeichnisse es und normale Dateien nicht. Der chmod-Rechner wandelt zwischen symbolischer und oktaler Schreibweise um, wenn du einen Modus vor dem Anwenden prüfen willst.