Operating System

Linux

Linux betreibt die große Mehrheit aller Server, Container und Cloud-Maschinen. Die wenigen Grundideen dahinter – alles ist eine Datei, Prozesse sind kostengünstig, Berechtigungen sind explizit – schalten jede Maschine frei, auf die Sie sich jemals per SSH einloggen werden.

beginner15 min readUpdated 16. Sept. 2026
server.sh
bash
# Update packages, then inspect and follow a service
sudo apt update && sudo apt upgrade -y
systemctl status nginx --no-pager
journalctl -u nginx -f
ss -tulpn | grep ':443'
Erstellt
1991
Schöpfer
Linus Torvalds
Lizenz
GPLv2
Kernel-Typ
Monolithic
Standard-Shells
bash, zsh, sh
Läuft auf
Servern, Containern, Telefonen, Routern

Warum es wichtig ist

Warum jeder Server, den Sie nutzen, Linux verwendet

Eine Schnittstelle, überall

Die gleichen Befehle funktionieren auf Ihrem Laptop, einem CI-Runner, einem Container und einer Cloud-VM. Lernen Sie die Shell einmal und Sie können jede Maschine untersuchen, auf die Sie Zugriff haben.

Berechtigungen sind explizit

Jede Datei hat einen Besitzer, eine Gruppe und einen Modus. Nichts läuft mit mehr Zugriff, als Sie ihm gewähren, was Shared-Server sicher macht.

Software ist nur einen Befehl entfernt

apt, dnf und apk installieren, aktualisieren und entfernen Software inklusive Abhängigkeitsauflösung, sodass eine frische Maschine in wenigen Minuten einsatzbereit ist.

Das Gesamtbild

Drei Ideen, die das gesamte System erklären

Ein Kernel vermittelt den Zugriff auf die Hardware, eine Shell wandelt Text in Befehle um und Prozesse sind so ressourcensparend, dass Tausende gleichzeitig laufen können.

Der Kernel

Vermitteln

Er plant Prozesse, verwaltet den Speicher und stellt Geräte als Dateien dar. Alles darüber kommuniziert über ihn mit der Hardware.

Die Shell

Befehlen

Ein Read-Eval-Loop über Text. Sie geben einen Programmnamen und Argumente ein, und die Shell findet das Binary in Ihrem PATH und führt es aus.

Prozesse

Ausführen

Jedes laufende Programm ist ein Prozess mit einer ID, einem Besitzer und einem Elternprozess. Services sind einfach langlebige Prozesse, die vom Init-System überwacht werden.

Linux auf einen Blick

Die Tools, die Sie tatsächlich nutzen werden

Das Dateisystem

Ein einziger Baum mit der Wurzel bei /, mit konventionellen Orten für Konfigurationen, Logs und Programme.

Die Shell

bash oder zsh mit History, Tab-Vervollständigung, Pipes und Redirection.

Berechtigungen

rwx-Bits für Besitzer, Gruppe und Andere, plus chmod und chown.

Prozesse

ps, top, kill und Signale, um laufende Arbeit zu untersuchen und zu steuern.

systemd

systemctl und journalctl zum Ausführen und Debuggen langlebiger Services.

Networking

ss, curl und dig, um Ports zu sehen, URLs abzurufen und DNS aufzulösen.

Eine kurze Geschichte

Vom Hobby-Kernel zum Cloud-Standard

  1. 1991

    Der Kernel erscheint

    Linus Torvalds veröffentlicht einen freien Unix-ähnlichen Kernel und lädt Mitwirkende ein.

    91
  2. 1992

    GNU trifft Linux

    Die Kombination der GNU-Tools mit dem Kernel ergibt ein vollständiges freies Betriebssystem.

    92
  3. 1993

    Distributionen entstehen

    Debian und Red Hat paketieren den Kernel mit Tools und bieten den Nutzern ein installierbares System.

    93
  4. 2004

    Ubuntu macht es benutzerfreundlich

    Ein vorhersehbarer Release-Zyklus und der Fokus auf den Desktop bringen Linux zu einem viel breiteren Publikum.

    04
  5. 2013

    Container laufen darauf

    Docker nutzt Linux-Namespaces und cgroups, um Prozesse zu isolieren, und läutet die Container-Ära ein.

    13
  6. Heute

    Das Standard-Server-OS

    Die meisten Public-Cloud-Instanzen, Container und die Mobilgeräte in Ihrer Tasche nutzen einen Linux-Kernel.

    Heute

Der vollständige Leitfaden

Linux: Alles was Sie wissen müssen

Warum Linux die Serverwelt beherrscht

Gehen Sie in ein beliebiges Rechenzentrum, öffnen Sie eine beliebige Cloud-Konsole oder docker exec in einen beliebigen Container, und Sie befinden sich fast sicher auf einem Linux-Kernel. Er treibt die Mehrheit der Webserver, jedes Android-Smartphone, die meisten Router und die überwältigende Mehrheit der Cloud-Instanzen an. Die Gründe dafür sind altbewährt: Es ist kostenlos, läuft auf fast jeder Hardware, ist stabil genug, um jahrelang ohne Unterbrechung zu laufen, und lässt sich von oben bis unten skripten.

Für Entwickler ist der praktische Aspekt spezifischer. In dem Moment, in dem Sie deployen, hören Sie auf, eine Person zu sein, die Dateien in einem Editor bearbeitet, und werden zu jemandem, der Befehle in eine Shell tippt – oft über SSH auf einer Maschine, die Sie nicht sehen können. Die Fähigkeiten in diesem Guide sind genau diejenigen, die diese Maschine lesbar machen, anstatt beängstigend.

Sie müssen kein Systemadministrator werden. Sie benötigen lediglich genügend Routine, um sich zurechtzufinden, Logs zu lesen, Berechtigungen zu korrigieren, einen Service neu zu starten und zu verstehen, welcher Prozess auf einem Port lauscht.

WSL und macOS: Du weißt bereits mehr, als du denkst

Wenn du macOS nutzt, befindest du dich bereits auf einem Unix-System. Das Terminal, die Struktur des Dateisystems und die meisten Befehle — ls, cd, grep, chmod, ssh — funktionieren auf die gleiche Weise. Die Unterschiede liegen hauptsächlich im Paketmanager und in einigen wenigen BSD- gegenüber GNU-Flags.

Unter Windows bietet dir WSL 2 einen echten Linux-Kernel innerhalb einer leichtgewichtigen virtuellen Maschine. wsl --install installiert dir Ubuntu mit einer Shell, und deine Dateien sind von beiden Seiten aus erreichbar. Dies ist der empfohlene Weg, da es dieselbe Umgebung ist, in der dein Code später laufen wird.

Selbst wenn du Linux nie direkt installierst, lässt sich das mentale Modell vollständig auf Container übertragen, welche im Grunde Linux-Userland-Prozesse in einem sehr überzeugenden Kostüm sind.

Das Dateisystem ist ein einziger Baum

Im Gegensatz zu Windows, wo Laufwerke separate Wurzeln bilden, hat Linux einen einzigen Baum mit der Wurzel bei /. Jede Festplatte, jeder Netzwerkshare und jedes Gerät wird irgendwo darin eingehängt (mounted). Eine Handvoll Verzeichnisse haben konventionelle Bedeutungen – wenn man diese kennt, weiß man immer, wo man suchen muss.

/           the root of everything
├── bin     essential user binaries (ls, cp, bash)
├── etc     system-wide configuration files
├── home    per-user home directories
├── opt     optional third-party software
├── proc    kernel and process state, as files
├── root    the root user's home
├── tmp     temporary files, cleared on reboot
├── usr     installed programs and libraries
│   ├── bin local binaries
│   └── lib shared libraries
└── var     variable data: logs, caches, databases
    ├── log system and application logs
    └── www web content on Debian systems

Die beiden Verzeichnisse, die Sie am häufigsten besuchen werden, sind /etc für Konfigurationen und /var/log für Logs. Wenn etwas nicht funktioniert, sind dies die ersten Orte, an denen man nachsieht. Wenn Sie eine Anwendung selbst installieren, halten /opt oder /usr/local diese vom Paketmanager fern.

Pfade sind entweder absolut (beginnen mit /, wie z. B. /etc/hosts) oder relativ (werden ausgehend von Ihrem aktuellen Verzeichnis aufgelöst). ~ ist eine Abkürzung für Ihr Home-Verzeichnis, . steht für das aktuelle Verzeichnis und .. für dessen übergeordnetes Verzeichnis. Diese drei Symbole tauchen in fast jedem Befehl auf, den Sie eingeben.

Alles ist eine Datei

Die grundlegendste Unix-Idee ist, dass fast alles als Datei dargestellt wird. Eine Festplatte ist /dev/sda. Ein Terminal ist /dev/pts/0. Informationen über laufende Prozesse befinden sich unter /proc/<pid>/. Zufallszahlen kommen aus /dev/urandom. Auch ein Unix-Domain-Socket ist eine Datei.

Diese Einheitlichkeit ist es, was die Shell so mächtig macht. Dieselben cat, grep, less und Redirection-Operatoren funktionieren bei einer Log-Datei, der Memory-Map eines Prozesses oder einem Device, da sie alle im Grunde nur Byte-Streams hinter einem Pfad sind. Wenn man das versteht, wirken /proc und /sys nicht mehr wie Magie, sondern werden analysierbar.

cat /proc/cpuinfo | grep 'model name' | head -1
ls -l /dev/null          # the bit bucket

Die Shell ist eine Schleife: Sie liest eine Zeile, erweitert sie, sucht das Programm und führt es aus. Sechs Befehle decken den Großteil der Navigation ab.

pwd                     # print working directory
ls -lah                 # list, long format, human sizes, hidden files
cd /var/log             # change directory
cd -                    # back to the previous directory
cd ~                    # home
tree -L 2               # a readable tree, two levels deep

Das Erstellen, Kopieren, Verschieben und Löschen von Dateien erfordert ein ebenso kleines Vokabular. mkdir -p erstellt bei Bedarf übergeordnete Verzeichnisse. cp -r kopiert Verzeichnisse rekursiv. mv benennt Dateien innerhalb eines Dateisystems um und verschiebt sie zwischen verschiedenen Dateisystemen. rm -rf löscht einen gesamten Verzeichnisbaum, weshalb dieser Befehl Respekt verdient: In der Kommandozeile gibt es keinen Papierkorb.

mkdir -p app/{src,test,docs}
cp -r app app.bak
mv notes.txt docs/notes.txt
rm -rf build/

Zwei Gewohnheiten sorgen für Ihre Sicherheit. Nutzen Sie ls oder find, um zu bestätigen, welche Dateien ein Glob-Pattern matcht, bevor Sie rm damit ausführen. Und bevorzugen Sie mv in ein Backup-Verzeichnis, anstatt etwas zu löschen, bei dem Sie unsicher sind. Die Shell-History ist kein Sicherheitsnetz, sobald Sie Enter drücken.

Dateien lesen, ohne einen Editor zu öffnen

Um etwas auf einem Server zu prüfen, benötigt man selten einen vollständigen Editor. Diese Tools geben nur den Teil aus, den Sie tatsächlich benötigen.

cat /etc/os-release          # print the whole file
less /var/log/syslog         # page through, / to search, q to quit
head -n 20 access.log        # first 20 lines
tail -n 50 access.log        # last 50 lines
tail -f app.log              # follow a live log
wc -l access.log             # count lines

tail -f ist der nützlichste Befehl während eines Incidents: Er streamt neue Zeilen in Echtzeit, während sie geschrieben werden. Drücken Sie Ctrl+C, um den Vorgang zu stoppen. less ist schneller als ein Editor und verändert die Datei niemals versehentlich, was besonders in Produktionsumgebungen wichtig ist.

Suchen mit find und grep

find durchläuft das Dateisystem und filtert nach Metadaten; grep durchsucht die Inhalte von Dateien. Zusammen beantworten sie die meisten „Wo ist das?“-Fragen.

find /etc -name '*.conf'                 # by name
find . -type d -name node_modules -prune -o -type f -name '*.ts' -print
find /var/log -type f -mtime -1          # modified in the last day
find . -type f -size +50M                # larger than 50 MB
find . -type f -name '*.tmp' -delete     # delete matches
grep -RIn 'TODO' src/                    # recursive, line numbers, ignore binary
grep -c 'ERROR' app.log                  # count matches
grep -E 'timeout|refused' app.log        # extended regex
grep -v '^#' config.ini                  # invert: drop comments

Wenn grep keine Ergebnisse liefert, ist dies ein Erfolg und kein Fehler, allerdings wird es mit dem Status 1 beendet. Das führt bei Skripten unter set -e oft zu Problemen; hängen Sie || true an, wenn ein leeres Ergebnis akzeptabel ist.

Berechtigungen: rwx und die oktale Kurzschreibweise

Jede Datei hat einen Besitzer, eine Gruppe und jeweils drei Berechtigungs-Bits: lesen (r), schreiben (w) und ausführen (x). ls -l zeigt diese als zehn Zeichen langen String an.

-rwxr-xr--  1 deploy www-data  512 Sep 16 10:00 deploy.sh
The ten-character permission string
-rwxr-xr--
type- file, d directory, l symlink
ownerread, write and execute for the owner
groupread and execute for the group
othersread only for everyone else

Oktal ist die Kurzschreibweise. Jedes Triplett ist die Summe aus 4 (lesen), 2 (schreiben) und 1 (ausführen), sodass rwx 7 ist, r-x 5 ist und r-- 4 ist. Das bedeutet, dass 755 für rwxr-xr-x steht und 644 für rw-r--r--.

chmod 755 deploy.sh          # scripts and directories
chmod 644 index.html         # regular files
chmod 600 .env               # secrets only the owner can read
chmod u+x,g-w,o-rwx script   # symbolic form, easier to review

Verzeichnisse benötigen das Execute-Bit, um betreten werden zu können. Deshalb verbirgt das Entfernen von x bei einem Verzeichnis dessen Inhalt, selbst wenn das Read-Bit noch gesetzt ist. Dies ist eine subtile Ursache für “permission denied”-Fehler, obwohl die Leseberechtigungen korrekt aussehen.

Besitz, Gruppen und umask

chown ändert den Besitzer und die Gruppe; chgrp ändert nur die Gruppe. Setzen Sie sudo als Präfix davor, da nur root Dateien übertragen kann.

sudo chown deploy:www-data /var/www/app
sudo chgrp -R www-data /var/www/app/uploads

Neue Dateien erhalten ihre Berechtigungen über die umask, eine Maske, die vom Standardwert abgezogen wird. Eine umask von 022 ergibt 644 für Dateien und 755 für Verzeichnisse; 027 ergibt 640 und 750. Setzen Sie diese in Ihrem Shell-Profil oder in der Unit-Datei eines Dienstes, wenn ein strengerer Standard erforderlich ist.

umask            # show current, e.g. 0022
umask 027        # stricter for this shell

sudo und die Gewohnheit der minimalen Rechtevergabe

sudo führt einen einzelnen Befehl als ein anderer Benutzer aus – standardmäßig als root –, nachdem /etc/sudoers überprüft wurde. Dies ist bewusst eng gefasst: Gewähren Sie nur die spezifischen Befehle, die eine Person oder ein Dienst benötigt, anstatt eine root-Shell bereitzustellen. Bevorzugen Sie sudo -u www-data <cmd>, anstatt Dateien als root zu bearbeiten und sie so im Besitz von root zu lassen.

sudo systemctl restart my-api
sudo -u postgres psql -c '\l'
sudo -l                      # what am I allowed to run?

Eine Faustregel: root besitzt die Systemkonfiguration, ein dedizierter Service-User besitzt die Anwendungsdateien und Ihre App läuft niemals als root. Wenn eine Kompromittierung Ihrer App einem Angreifer root-Rechte auf dem Host verschaffen würde, sind die Berechtigungen wirkungslos.

Benutzer und Gruppen

Benutzer werden durch einen Namen und eine numerische uid identifiziert; Gruppen durch einen Namen und eine gid. Das Mapping befindet sich in /etc/passwd und /etc/group, während die gehashten Passwörter in /etc/shadow gespeichert sind und nur für root lesbar sind.

whoami                       # current user
id                           # uid, gid and groups
groups deploy                # groups a user belongs to
sudo adduser appuser         # create a user (Debian/Ubuntu)
sudo usermod -aG docker appuser   # add to a group
sudo userdel -r appuser      # remove the user and home

Service-Accounts haben in der Regel kein Passwort und keine Login-Shell. Das ist beabsichtigt: Sie existieren dazu, Dateien zu besitzen und einen einzelnen Prozess auszuführen, nicht um sich darin einzuloggen.

Prozesse: ps, top und Signale

Jedes laufende Programm ist ein Prozess mit einer pid, einem Besitzer und einem Elternprozess. ps erstellt eine Momentaufnahme; top und htop aktualisieren live.

ps aux | grep node           # find a process
ps -eo pid,ppid,user,%cpu,%mem,cmd --sort=-%cpu | head
top -o %MEM                  # interactive, sort by memory
pgrep -af node               # pids and full command lines

Prozesse kommunizieren über Signale. SIGTERM (15) bittet einen Prozess, zu beenden, und ist der Standard für kill; SIGINT (2) ist Ctrl+C; SIGHUP (1) bedeutet traditionell ein Neuladen; SIGKILL (9) kann nicht abgefangen werden und sollte das letzte Mittel sein.

kill 1234            # SIGTERM, graceful
kill -HUP 1234       # reload config
kill -9 1234         # force, no cleanup
pkill -f 'node server.js'

Sende zuerst SIGTERM und gib dem Prozess einige Sekunden Zeit, um Verbindungen zu schließen und den Status zu flushen. Eskaliere erst zu -9, wenn der Prozess wirklich feststeckt, da dieser jeden Cleanup-Pfad deiner App überspringt.

Hintergrundjobs, & und nohup

Das Anhängen von & führt einen Befehl im Hintergrund aus; jobs, fg und bg dienen dazu, diesen aus der aktuellen Shell heraus zu verwalten. Ein Hintergrundjob wird jedoch trotzdem beendet, wenn Sie das Terminal schließen, es sei denn, Sie lösen ihn mit nohup oder einem Terminal-Multiplexer vom Hangup-Signal.

long-task &              # background in this shell
jobs -l                  # list background jobs
fg %1                    # bring job 1 to the foreground
nohup ./worker.sh > worker.log 2>&1 &
disown                   # detach from the shell's job table

Für alles, was länger laufen soll, nutzen Sie tmux oder screen. Diese halten eine Session auch bei Verbindungsabbrüchen aufrecht, was extrem wertvoll ist, wenn ein Deploy länger dauert als Ihre SSH-Verbindung.

tmux new -s deploy
# Ctrl+B, then D to detach
tmux attach -t deploy

systemd services mit systemctl

Auf modernen Distributionen ist systemd das Init-System, das Services beim Bootvorgang startet und überwacht. Sie definieren einen Service in einer Unit-Datei unter /etc/systemd/system/.

# /etc/systemd/system/my-api.service
[Unit]
Description=My API
After=network.target

[Service]
Type=simple
User=appuser
WorkingDirectory=/opt/my-api
Environment=NODE_ENV=production
EnvironmentFile=/opt/my-api/.env
ExecStart=/usr/bin/node server.js
Restart=on-failure
RestartSec=3

[Install]
WantedBy=multi-user.target

Nachdem Sie eine Unit erstellt oder bearbeitet haben, laden Sie den Manager neu und aktivieren Sie den Service, damit dieser beim Booten startet.

sudo systemctl daemon-reload
sudo systemctl enable --now my-api
systemctl status my-api --no-pager
sudo systemctl restart my-api
sudo systemctl reload my-api      # if the service supports it

Restart=on-failure ist das Feature, das einen abgestürzten Prozess in einen selbstheilenden Service verwandelt. EnvironmentFile hält Secrets aus der Unit fern, welche oft weltweit lesbar ist. Verwenden Sie Type=notify nur, wenn das Programm das Notification-Protokoll tatsächlich unterstützt; simple ist der sichere Standardwert.

Logs mit journalctl

systemd fängt stdout und stderr eines Services im Journal ab. journalctl fragt dieses ab und ihr werdet es ständig benutzen.

journalctl -u my-api                 # all logs for one unit
journalctl -u my-api -n 100          # last 100 lines
journalctl -u my-api -f              # follow live
journalctl -u my-api --since today
journalctl -u my-api --since '10 min ago' -p err
journalctl -b -p warning             # this boot, warnings and worse
journalctl --disk-usage
sudo journalctl --vacuum-time=7d     # keep a week

Das Flag -p filtert nach Priorität, von emerg bis hin zu debug. Einem Unit mit -f zu folgen, während ihr einen Endpoint aufruft, ist der schnellste Weg, um die Ursache eines 500-Fehlers zu finden.

Umgebungsvariablen und PATH

Umgebungsvariablen sind Key-Value-Strings, die ein Prozess von seinem Elternprozess erbt. PATH ist dabei die wichtigste: Hier werden die Verzeichnisse aufgelistet, in denen die Shell nacheinander nach einem Befehlsnamen sucht.

echo "$PATH" | tr ':' '\n'
export NODE_ENV=production
export PATH="$HOME/.local/bin:$PATH"
printenv DATABASE_URL

Da ein Service nicht deine interaktive Shell erbt, setze Variablen in seiner Unit-Datei oder in einer EnvironmentFile. Wenn eine Variable in deinem Terminal funktioniert, aber nicht unter systemd, ist fast immer dies die Ursache. Um deine eigenen Einstellungen dauerhaft zu speichern, füge die export-Zeilen zu ~/.bashrc oder ~/.profile hinzu.

Paketmanager: apt, dnf, apk

Jede Distributionsfamilie hat ihren eigenen Paketmanager, aber die Befehle sind ähnlich: Index aktualisieren, installieren, upgraden, entfernen, suchen.

# Debian / Ubuntu
sudo apt update && sudo apt upgrade -y
sudo apt install nginx
sudo apt remove --purge nginx

# Fedora / RHEL
sudo dnf install nginx
sudo dnf upgrade --refresh

# Alpine (common in containers)
sudo apk add nginx
sudo apk upgrade

Installieren Sie nach Möglichkeit nur aus offiziellen Repositories; diese sind signiert und gepatcht. Nutzen Sie PPAs oder Drittanbieter-Repos nur bewusst und pinnen Sie Versionen in Produktions-Images, damit ein Rebuild nicht stillschweigend die laufende Software ändert.

Pipes, Redirection und kleine Skripte

Ein Pipe leitet die Ausgabe eines Programms in die Eingabe eines anderen weiter. Redirection leitet diese entweder in eine Datei um oder liest sie aus einer aus. Zusammen verwandeln sie kleine Tools in Pipelines.

ls -l | wc -l                     # count files
grep ' 500 ' access.log | wc -l   # count 500s
cmd > out.txt                     # stdout to file, overwrite
cmd >> out.txt                    # append
cmd 2> err.txt                    # stderr to file
cmd > all.txt 2>&1                # both streams together
cmd < input.txt                   # read stdin from a file

Jeder Prozess startet mit drei File-Deskriptoren: stdin (0), stdout (1) und stderr (2). 2>&1 bedeutet „leite stderr dorthin weiter, wo auch stdout hingeht“, wobei die Reihenfolge entscheidend ist – es muss nach der stdout-Redirection stehen.

Wenn du eine solche Sequenz in ein Skript packst, hast du eine Automatisierung. Zwei Zeilen am Anfang machen Skripte wesentlich sicherer:

#!/usr/bin/env bash
set -euo pipefail

-e beendet das Skript beim ersten fehlgeschlagenen Befehl, -u meldet Fehler bei undefinierten Variablen und -o pipefail lässt eine Pipeline fehlschlagen, wenn eine beliebige Stufe darin fehlschlägt. Zusammen verwandeln sie stille Teilfehler in deutliche Fehlermeldungen – genau das, was man in einem Deploy-Skript möchte.

SSH und Keys

SSH ist die Methode, mit der du auf eine Remote-Maschine zugreifst. Passwort-Logins funktionieren zwar, aber Keys sind sicherer und lassen sich automatisieren. Du behältst einen Private Key geheim und hinterlegst den passenden Public Key auf dem Server.

ssh-keygen -t ed25519 -C "you@laptop"      # creates ~/.ssh/id_ed25519(.pub)
ssh-copy-id [email protected]            # install the public key
ssh [email protected]                    # log in

Ein Host-Alias in ~/.ssh/config erspart Tipparbeit und fixiert nützliche Optionen:

Host prod
  HostName 203.0.113.10
  User deploy
  IdentityFile ~/.ssh/id_ed25519
  ServerAliveInterval 30

Anschließend verbindet ssh prod die Sitzung. Sobald du Keys vertraust, solltest du die Passwort-Authentifizierung in /etc/ssh/sshd_config (PasswordAuthentication no) deaktivieren und sshd neu laden. scp und rsync verwenden dieselben Keys zum Kopieren von Dateien; rsync -avz --delete ist der übliche Weg, um ein Verzeichnis zu synchronisieren.

rsync -avz --exclude node_modules ./app/ prod:/opt/app/
ssh prod 'sudo systemctl restart my-api'

Festplatte und Arbeitsspeicher: df, du, free

Server fallen selten wegen der CPU aus; sie fallen aus, weil eine Festplatte vollläuft oder der Arbeitsspeicher aufgebraucht ist. Diese Befehle beantworten die Fragen „Wie viel ist noch übrig?“ und „Wer verbraucht den Platz?“.

df -h                       # free space per filesystem
df -i                       # inode usage — a disk can be full of inodes
du -sh /var/log/*           # size per entry
du -h --max-depth=1 / | sort -h
free -h                     # memory and swap
ls -lhS /var/log | head     # biggest log files

Wenn /var voll ist, sind fast immer Logs, ein Paket-Cache oder eine außer Kontrolle geratene Datenbank die Ursache. Räumen Sie gezielt auf — journalctl --vacuum-time, apt clean, Log-Rotation — anstatt Dateien zu löschen, die eine Anwendung erwartet.

Networking: ss, curl, dig

ss zeigt Sockets und listening ports an und ersetzt das ältere netstat. Es beantwortet die Frage: „Hört irgendetwas zu und wer ist verbunden?“.

ss -tulpn                   # TCP, UDP, listening, process names
curl -I https://example.com # response headers only
curl -sS localhost:3000/health
curl -X POST -H 'content-type: application/json' \
  -d '{"name":"ada"}' localhost:3000/users
dig example.com +short      # DNS resolution
dig @1.1.1.1 example.com MX

curl -I ist der schnellste Weg, um zu bestätigen, dass ein Server antwortet und welchen Status er zurückgibt. Wenn ss nichts auf einem Port anzeigt, die App aber meldet, dass sie gestartet ist, ist sie möglicherweise an 127.0.0.1 statt an 0.0.0.0 gebunden, was von außerhalb des Hosts nicht sichtbar ist.

Zeitplanung mit cron

cron führt Befehle nach einem festgelegten Zeitplan aus. Jeder Benutzer verfügt über eine crontab mit fünf Zeitfeldern, gefolgt vom eigentlichen Befehl.

# ┌ min (0-59)
# │ ┌ hour (0-23)
# │ │ ┌ day of month (1-31)
# │ │ │ ┌ month (1-12)
# │ │ │ │ ┌ day of week (0-6, Sun=0)
# * * * * * command
crontab -e                    # edit your crontab
crontab -l                    # list it
0 3 * * * /opt/app/backup.sh >> /var/log/backup.log 2>&1
*/5 * * * * curl -fsS localhost:3000/health > /dev/null
0 7 * * 1 /opt/app/weekly-report.sh

Die Umgebung von cron ist minimal: Sie hat einen anderen PATH, kein Shell-Profil und keine interaktiven Variablen. Verwenden Sie absolute Pfade, leiten Sie die Ausgabe in ein Log um, damit Fehler sichtbar sind, und denken Sie daran, dass cron einen fehlgeschlagenen Durchlauf nicht automatisch wiederholt. Für komplexere Anforderungen sollten Sie stattdessen einen systemd-Timer planen oder einen Job in eine Queue einreihen.

Best Practices

  • Verwenden Sie in Skripten und Unit-Dateien absolute Pfade; verlassen Sie sich niemals auf die interaktive Umgebung.
  • Setzen Sie set -euo pipefail an den Anfang jedes nicht-trivialen Shell-Skripts.
  • Gewähren Sie minimale Berechtigungen: dedizierte Service-User, sudo für spezifische Befehle, keine App, die als root läuft.
  • Bevorzugen Sie SIGTERM und lassen Sie Services ordnungsgemäß herunterfahren, bevor Sie zu kill -9 greifen.
  • Konfigurieren Sie Restart=on-failure und lesen Sie journalctl -u <unit> beim Debugging.
  • Halten Sie die Konfiguration in der Versionsverwaltung und ändern Sie auf einem Live-Host immer nur eine Sache gleichzeitig.
  • Rotieren Sie Logs und behalten Sie df -h und df -i im Auge; Festplatten füllen sich lautlos.
  • Verwenden Sie SSH-Keys statt Passwörter und speichern Sie private Keys nicht auf Servern.
  • Lernen Sie find, grep, awk und Pipes — sie ersetzen viele Einzellösungen.
  • Testen Sie eine Konfiguration, bevor Sie den Service neu laden, der sie einliest.

Häufige Fehler

  • Anwendungen als root ausführen und so jeden Bug in eine vollständige Kompromittierung des Systems verwandeln.
  • chmod -R 777 verwenden, um Berechtigungen zu “fixen”, wodurch jeder Schutz zwischen Benutzern entfernt wird.
  • Dateien mit einem ungeprüften Wildcard und ohne Backup löschen.
  • Zuerst kill -9 senden und dadurch den State korrumpieren, den ein graceful shutdown ordnungsgemäß geschrieben hätte.
  • Umgebungsvariablen in der Shell setzen und erwarten, dass systemd diese erkennt.
  • Davon ausgehen, dass ein Dienst down ist, obwohl er nur an 127.0.0.1 gebunden ist.
  • 2>&1 in cron-Einträgen vergessen und dadurch die Fehlermeldung verlieren, die ein fehlgeschlagenen Job erklärt.
  • Konfigurationen direkt auf einem Server ohne Versionsverwaltung bearbeiten, ohne eine Möglichkeit zum Zurückrollen zu haben.
  • Die Erschöpfung der Inodes ignorieren, weil df -h immer noch freien Speicherplatz anzeigt.
  • Die Passwort-Authentifizierung an einem öffentlich zugänglichen SSH-Port aktiviert lassen.

Wie geht es weiter?

Linux ist das Fundament für alles, was du deployst. Sobald du dich auf einem Server zurechtfindest, Logs lesen und Dienste neu starten kannst, zeigt dir der Nginx-Guide den Webserver, den du vor deine App schaltest. Docker & Deployment verwandelt diese Grundlagen in wiederholbare, isolierte Images. Um dieselben Befehle bei jedem Push zu automatisieren, lies den Guide zu CI/CD, und um den Prozess zu verstehen, unter dem dein Service tatsächlich läuft, schau dir noch einmal die Node.js Basics an.

In der Praxis

Die Shell-Befehle für den Alltag

Vier Gruppen, die man auswendig lernen sollte, bevor man eine Produktionsmaschine berührt.

files.sh
pwd                          # where am I?
ls -lah /var/log             # long, human sizes, hidden files
cd /etc/nginx && cd -        # go there, then back
mkdir -p app/{src,test}      # create nested dirs in one shot
cp -r src backup/            # copy a tree
mv old.txt new.txt           # rename or move
rm -rf node_modules          # delete a tree (be careful)

# find files by name, size or age
find /var/log -name '*.log' -mtime -7
find . -type f -size +100M -exec ls -lh {} \;

chmod 755 vs chmod 777

777 entfernt den Schutz zwischen Benutzern. Fast nichts benötigt dies, und ein web-beschreibbares Verzeichnis ist ein häufiger Weg, wie eine Seite kompromittiert wird.

Bevorzugt
chmod 755 script.sh   # rwxr-xr-x
chmod 644 index.html  # rw-r--r--
chmod 600 .env        # rw-------
chmod 700 ~/.ssh      # rwx------
Vermeiden
chmod -R 777 /var/www
# anyone on the box can edit
# or replace your code

kill vs kill -9

SIGTERM bittet einen Prozess, sich herunterzufahren, damit er Verbindungen schließen und den Status speichern kann. SIGKILL kann nicht abgefangen werden und lässt dem Prozess keine Chance.

Bevorzugt
kill 1234        # SIGTERM: graceful
# wait, then escalate only
# if it is truly stuck
Vermeiden
kill -9 1234     # SIGKILL: no cleanup
# can corrupt files and
# drop in-flight requests

Häufig gestellte Fragen

Häufig gestellte Fragen

Keep learning

Related topics from the roadmap.

$ Lernen Sie jetzt

Bereit, Linux Basics zu lernen?

Unser interaktives Tutorial führt Sie Schritt für Schritt durch Linux Basics — mit Quizzen und echtem Code, den Sie im Browser ausführen können.