/run ist ein tmpfs-basiertes Verzeichnis (reiner RAM-Speicher), das Laufzeit-Zustände aktiver Dienste aufnimmt: PID-Files, Unix-Domain-Sockets, Lock-Files, Datenbanken kurzlebiger Sessions. Nach einem Reboot ist es leer — genau das gewünschte Verhalten, weil die Daten nur für laufende Prozesse Sinn ergeben. Auf modernen systemd-Systemen sind /var/run und /var/lock Symlinks auf /run bzw. /run/lock.
Was ist /run?
/run ist seit FHS 3.0 (2015) der offizielle Pfad für Runtime-State — kurzlebige Daten, die nur Sinn ergeben, solange das System läuft. Drei Eigenschaften definieren das Verzeichnis:
- tmpfs im RAM, also flüchtig und schnell.
- Beim Boot sehr früh verfügbar — noch bevor
/vargemountet sein muss. - Pro System eindeutig:
/runselbst ist global,/run/user/<uid>/pro User.
mount | grep ' /run '
# tmpfs on /run type tmpfs (rw,nosuid,nodev,size=...,mode=755)
# Größe und Belegung
df -h /run
# tmpfs 787M 4.2M 783M 1% /run
# Inhalt auf einen Blick
ls /run/
# NetworkManager dbus lock systemd
# blkid log mount udev
# cron.reboot lvm sshd.pid userWas du in /run findest:
| Inhalt | Beispiel |
|---|---|
| PID-Files aktiver Daemons | /run/sshd.pid, /run/cron.pid |
| Unix-Domain-Sockets für IPC | /run/dbus/system_bus_socket, /run/docker.sock |
| Lock-Files | /run/lock/<service> (Sticky-Bit gesetzt) |
| systemd-Unterverzeichnisse | /run/systemd/system/, /run/systemd/journal/ |
| udev-Datenbank | /run/udev/data/ |
| Pro-User-Runtime-Dirs | /run/user/1000/ (für UID 1000) |
| Mount-Punkt-State | /run/mount/, /run/blkid/blkid.tab |
Geschichte: von /var/run nach /run
Bis ca. 2012 lagen diese Daten unter /var/run (System) und /var/lock (Locks). Das hatte zwei Probleme:
/varwird erst spät im Boot-Prozess gemountet — Init-Scripts, die schon vorher PID-Files schreiben mussten, hatten ein Henne-Ei-Problem./var/runwurde selten als tmpfs gemountet — es konnte beim Crash unaufgeräumte Reste enthalten, die einen Service-Neustart blockierten.
Der Übergang zu systemd (Fedora 15 als erste Distro 2011, Debian 8 als „Jessie" 2015) brachte /run als eigenständiges tmpfs, das vor /var aktiv ist. Aus Kompatibilitäts-Gründen sind die alten Pfade jetzt Symlinks:
ls -la /var/run /var/lock
# lrwxrwxrwx 1 root root 4 ... /var/lock -> /run/lock
# lrwxrwxrwx 1 root root 4 ... /var/run -> /run
# Effekt: dieselben Dateien, zwei Pfade
echo "test" > /tmp/test
ls -la /run/sshd.pid /var/run/sshd.pid
# -rw-r--r-- 1 root root 6 ... /run/sshd.pid
# -rw-r--r-- 1 root root 6 ... /var/run/sshd.pid ← gleiche DateiProgramme können also /var/run/sshd.pid weiter ansprechen — der Symlink leitet transparent um. Neue Software sollte aber direkt /run/<name>.pid verwenden.
Pro-User: $XDG_RUNTIME_DIR und /run/user/
Eine wichtige Innovation seit systemd: pro Login-User wird ein eigenes Runtime-Verzeichnis angelegt — /run/user/<UID>/. Es gehört dem User mit Mode 0700, sodass nur er hineinschauen darf, und wird bei seinem Logout automatisch entfernt.
Die Standard-Variable $XDG_RUNTIME_DIR zeigt darauf:
echo "$XDG_RUNTIME_DIR"
# /run/user/1000
ls -la "$XDG_RUNTIME_DIR"
# drwx------ 13 michael michael 340 ... .
# ...
# drwxr-xr-x 2 michael michael 80 ... pulse
# srw-rw---- 1 michael michael 0 ... bus ← dbus-Socket
# srw-rw---- 1 michael michael 0 ... pulse/native ← PulseAudio
# drwxr-xr-x 3 michael michael 60 ... systemd
# ...
# Gehört uns alleine
stat -c '%a %U:%G' "$XDG_RUNTIME_DIR"
# 700 michael:michaelWas hier alles landet:
- dbus-Session-Socket für User-Apps
- PulseAudio-Socket
- GnuPG-Agent-Socket
- systemd --user-Sockets und PID-Files
- Wayland-Display-Socket (
wayland-0,wayland-0.lock)
Das ist die richtige Stelle für kurzlebige User-Daten, die nicht persistent sein müssen. Skripte, die einen User-Socket anlegen wollen, gehören dorthin — nicht nach /tmp (wo andere User reinschauen können) und nicht nach ~/.local/state/ (wo der Reboot nichts bringt).
/run/lock und Sticky-Bit
/run/lock (vorher /var/lock) hat das Sticky-Bit gesetzt (Mode 1777), damit User Lock-Files anlegen können, ohne dass andere sie löschen:
ls -ld /run/lock
# drwxrwxrwt 4 root root 80 ... /run/lock
# Klassisches Beispiel: serielle Ports
ls /run/lock/
# subsys/ ← Service-Locks (z. B. cron, exim4)
# LCK..ttyUSB0 ← Lock für seriellen PortHeute werden Lock-Files seltener manuell genutzt — moderne Programme bevorzugen flock() auf der Original-Datei (atomarer, aufräum-freundlicher). Das /run/lock-Pattern bleibt aber für Legacy-Software und einige Daemons aktiv.
Praxis: Sockets und PID-Files inspizieren
/run ist die erste Anlaufstelle, um zu prüfen, ob ein Service läuft und wie man mit ihm spricht:
# PID eines Daemons aus dem File lesen
cat /run/sshd.pid
# 1234
# Prüfen, ob der Prozess wirklich läuft
kill -0 $(cat /run/sshd.pid) && echo "läuft" || echo "tot"
# Was steckt sonst noch in /run?
find /run -maxdepth 2 -name '*.pid' 2>/dev/null# Alle Unix-Sockets im /run-Baum
find /run -type s 2>/dev/null
# /run/docker.sock
# /run/dbus/system_bus_socket
# /run/systemd/notify
# /run/user/1000/pulse/native
# ...
# Wer hört auf welchem Socket?
sudo lsof -U /run/docker.sock
# COMMAND PID USER FD TYPE ... NAME
# dockerd 1023 root 3u unix ... /run/docker.sock# Aktive Units, die nicht persistent installiert sind
ls /run/systemd/system/
# session-c1.scope.d/ user-1000.slice.d/ ...
# systemd-private Tmp-Verzeichnis pro Service (PrivateTmp=yes)
sudo ls /run/systemd/private-* 2>/dev/nullEigene Services: in /run schreiben
Wer einen eigenen Service schreibt, sollte PID-File und Socket nach /run/<servicename>/ legen — nicht in /tmp und nicht in /var. systemd hilft dabei mit der RuntimeDirectory=-Direktive:
# /etc/systemd/system/myapp.service
[Unit]
Description=Mein Service
After=network.target
[Service]
Type=simple
User=myapp
Group=myapp
ExecStart=/usr/local/bin/myapp --socket /run/myapp/sock --pid /run/myapp/pid
# systemd legt /run/myapp/ automatisch beim Start an,
# gehört User "myapp", Mode 0750 — und entfernt es beim Stop.
RuntimeDirectory=myapp
RuntimeDirectoryMode=0750
[Install]
WantedBy=multi-user.targetVorteile dieser Direktive:
- Automatisches Anlegen:
/run/myapp/existiert beim Start, ohne dass das Programm es selbst tun muss. - Saubere Berechtigungen: gehört dem konfigurierten User, nicht root.
- Automatisches Entfernen: beim Service-Stop wird das Verzeichnis entfernt — kein zurückbleibender Müll.
Interessantes
/var/run-Pfade in alter Doku einfach umlenken
Wer in alten Tutorials oder Manpages auf /var/run/sshd.pid stößt, muss nicht panisch werden — der Symlink-Pfad funktioniert weiter. Für eigene neue Skripte aber direkt /run/sshd.pid verwenden.
$XDG_RUNTIME_DIR ist nur in interaktiven Sessions gesetzt
Bei Cron-Jobs oder systemd-Units, die ohne Login-Session laufen, ist $XDG_RUNTIME_DIR leer. Skripte, die sie verwenden, sollten einen Fallback haben — etwa /run/user/$(id -u) oder mktemp -d als Notlösung. Sonst schlägt der Skript-Lauf in der Cron-Umgebung still fehl.
/run wächst nicht — bis es es tut
tmpfs ist standardmäßig 10–20 % des RAMs als Limit. Auf Systemen mit sehr vielen Services oder vielen User-Sessions kann sich /run füllen — typischerweise durch übergroße Logfiles in /run/log/ oder vergessene Drop-In-Verzeichnisse. df -h /run und du -sh /run/* regelmäßig prüfen.
PID-Files sind ein Race-Risiko
Klassisches Pattern: Skript liest PID aus File, prüft mit kill -0, fängt Race-Condition. Wenn der Prozess in dem Moment endet und seine PID neu vergeben wird, „tötet" das Skript einen unbeteiligten Prozess. Sicherer: systemd's MainPID direkt aus systemctl show lesen oder flock für Lock-Files verwenden.
Wayland-Sockets liegen nur in /run/user/
Das wayland-0-Socket eines Wayland-Servers liegt unter $XDG_RUNTIME_DIR/wayland-0. Wer eine Wayland-Anwendung von einer anderen User-Session aus starten will (etwa ein anderer User per sudo -u), muss XDG_RUNTIME_DIR und WAYLAND_DISPLAY korrekt mit setzen — sonst sieht die Anwendung kein Display.
Container haben ein eigenes /run
Im Container-Namespace ist /run ein eigenes tmpfs, völlig getrennt vom Host. Sockets sind also nicht direkt sichtbar — wer Docker-Socket-Zugriff im Container braucht, mountet /run/docker.sock explizit per -v /run/docker.sock:/run/docker.sock. Das ist ein erheblicher Sicherheits-Risiko (Container kann den Host steuern), wird aber für CI-Tools verbreitet genutzt.
Weiterführende Ressourcen
Externe Quellen
- Filesystem Hierarchy Standard 3.0 — /run
- systemd: RuntimeDirectory= in systemd.exec(5)
- XDG Base Directory Specification — XDG_RUNTIME_DIR
- Linux man-pages: pid_namespaces(7)
- Linux man-pages: hier(7)