Geräte-Events automatisch verarbeiten
Sobald ein Server mehrere Netzwerkkarten, zusätzliche Storage-Geräte oder USB-Hardware bekommt, reicht die automatische Standardbenennung durch den Kernel oft nicht mehr aus: Nach einem Neustart heißt die gestern noch als sdb erkannte Festplatte plötzlich sdc, und ein Skript, das sich auf diesen Namen verlässt, greift ins Leere. udev löst genau dieses Problem, indem es Kernel-Device-Events abfängt und darauf mit selbst definierten Regeln reagiert, von persistenten Namen bis zu automatisch gestarteten Aktionen.
Inhaltsverzeichnis
- 1. Wie udev Kernel-Device-Events verarbeitet
- 2. Regel-Syntax: Match-Keys und Assign-Keys
- 3. Eigene Regeldateien in /etc/udev/rules.d anlegen
- 4. Praxisbeispiel: Persistente Device-Namen für Storage-Geräte
- 5. Regeln mit udevadm testen und debuggen
- 6. RUN+= Aktionen und typische Timing-Fallstricke
- 7. Zusammenspiel von udev und systemd Device-Units
- 8. Praxisbeispiel: Persistente Namen für Netzwerkkarten setzen
- 9. Best Practices und Debugging im laufenden Betrieb
- 10. Zusammenfassung
- 11. FAQ
1. Wie udev Kernel-Device-Events verarbeitet
Immer wenn der Kernel ein Gerät erkennt, egal ob beim Boot oder beim nachträglichen Einstecken einer USB-Festplatte, sendet er ein sogenanntes Uevent über den Netlink-Socket an den Userspace. udev, seit einigen Jahren fester Bestandteil von systemd, empfängt dieses Event, reichert es mit zusätzlichen Informationen aus sysfs an und entscheidet anhand seiner Regeln, wie darauf reagiert wird.
Diese Trennung zwischen Kernel und Userspace ist bewusst gewählt: Der Kernel selbst kennt keine Konzepte wie Gerätenamen nach Belieben, Berechtigungen für bestimmte Benutzergruppen oder das automatische Starten eines Skripts. All das übernimmt udev im Userspace, was die Konfiguration flexibel und ohne Kernel-Neustart änderbar macht, während der Kernel selbst schlank und generisch bleibt.
# Uevents in Echtzeit beobachten, während ein Geraet an- oder abgesteckt wird
udevadm monitor --udev --property
2. Regel-Syntax: Match-Keys und Assign-Keys
Jede udev-Regel besteht aus einer Kombination von Match-Keys, die mit dem doppelten Gleichheitszeichen == geschrieben werden und bestimmen, ob eine Regel überhaupt greift, sowie Assign-Keys mit einfachem Gleichheitszeichen =, die eine Aktion oder Eigenschaft setzen. Typische Match-Keys sind KERNEL für den vom Kernel vergebenen Gerätenamen, SUBSYSTEM für die Geräteklasse wie block oder net, und ATTR{...} für Attribute aus sysfs.
Assign-Keys wie SYMLINK+=, OWNER=, MODE= oder RUN+= bestimmen, was mit dem Gerät passiert, sobald alle Match-Bedingungen einer Regel zutreffen. Das Pluszeichen bei SYMLINK+= und RUN+= ist wichtig: Es ergänzt vorhandene Werte, statt sie zu überschreiben, sodass mehrere Regeln unabhängig voneinander zusätzliche Symlinks oder Aktionen beisteuern können.
3. Eigene Regeldateien in /etc/udev/rules.d anlegen
Distributionen liefern Standardregeln in /usr/lib/udev/rules.d/ aus, die bei einem Paket-Update überschrieben werden können. Eigene Regeln gehören deshalb ausschließlich in /etc/udev/rules.d/, das Vorrang vor den Standardregeln hat und von Paket-Updates unberührt bleibt. Der Dateiname folgt der Konvention einer zweistelligen Prioritätsnummer gefolgt von einem beschreibenden Namen, etwa 70-persistent-storage.rules.
Die Priorität entscheidet über die Verarbeitungsreihenfolge: Niedrigere Nummern werden zuerst ausgewertet. Regeln im Bereich 60 bis 69 sind traditionell für persistente Gerätenamen reserviert, während Regeln ab 90 aufwärts typischerweise Aktionen wie das Starten von Skripten oder Diensten auslösen, nachdem grundlegende Eigenschaften bereits gesetzt wurden.
# Eigene Regeldatei anlegen, mit Nummer für die Verarbeitungsreihenfolge
sudo nano /etc/udev/rules.d/70-persistent-storage.rules
# Nach Änderungen: Regeln neu einlesen, ohne den Server neu zu starten
sudo udevadm control --reload-rules
sudo udevadm trigger
4. Praxisbeispiel: Persistente Device-Namen für Storage-Geräte
Klassische Kernel-Namen wie /dev/sdb sind nicht garantiert stabil, weil die Reihenfolge der Geräteerkennung beim Boot variieren kann, etwa wenn eine externe Festplatte etwas später als erwartet erkannt wird. Für Storage in Produktionsservern, insbesondere bei RAID- oder LVM-Setups, ist deshalb ein stabiler, hardwaregebundener Name entscheidend, der sich nicht mit der Boot-Reihenfolge ändert.
Eine eigene Regel kann dafür die Seriennummer des Datenträgers aus sysfs auslesen und daraus einen zusätzlichen, garantiert stabilen Symlink erzeugen. Ergänzend liefert udev bereits standardmäßig Symlinks unter /dev/disk/by-id/, /dev/disk/by-uuid/ und /dev/disk/by-path/, die für die meisten Fälle bereits ausreichen und in /etc/fstab statt der rohen /dev/sdX Bezeichnung verwendet werden sollten.
# /etc/udev/rules.d/70-persistent-storage.rules
# Eigenen, stabilen Symlink basierend auf der Seriennummer anlegen
SUBSYSTEM=="block", KERNEL=="sd?", ENV{ID_SERIAL}=="WD-WCC4N1234567", \
SYMLINK+="disk/backup-volume"
# Vorhandene, von udev automatisch erzeugte Symlinks anzeigen
ls -la /dev/disk/by-id/
5. Regeln mit udevadm testen und debuggen
Bevor eine neue Regel produktiv verwendet wird, zeigt udevadm info alle verfügbaren Eigenschaften eines bereits vorhandenen Geräts, die als Match-Keys in einer Regel infrage kommen. Das ist der erste Schritt bei jeder neuen Regel, weil es zuverlässiger ist, tatsächlich vorhandene Attribute abzulesen, als sie zu erraten.
Für die eigentliche Regel-Simulation eignet sich udevadm test, das den Regel-Durchlauf für ein bestimmtes Gerät simuliert und detailliert protokolliert, welche Regeln greifen und welche Aktionen ausgelöst würden, ohne das System tatsächlich zu verändern. Erst nach einem erfolgreichen Testlauf sollte udevadm trigger die Regeln tatsächlich auf laufende Geräte anwenden.
# Alle Eigenschaften eines Geraets für Match Keys anzeigen
udevadm info --query=all --name=/dev/sdb
# Regel Verarbeitung simulieren, ohne das System zu verändern
udevadm test /sys/class/block/sdb
# Regeln tatsaechlich auf bereits vorhandene Geraete anwenden
udevadm trigger --subsystem-match=block
6. RUN+= Aktionen und typische Timing-Fallstricke
Der Assign-Key RUN+= startet ein externes Programm, sobald die Regel greift. Ein häufiger Anfängerfehler ist der Versuch, damit langlaufende Prozesse direkt zu starten: udev-Regeln müssen extrem schnell abgearbeitet werden, und ein blockierender Aufruf innerhalb von RUN+= verzögert die Verarbeitung aller nachfolgenden Uevents, im schlimmsten Fall systemweit.
Die korrekte Lösung für längere Aktionen ist, über RUN+="/usr/bin/systemd-run ..." einen eigenständigen systemd Transient-Service zu starten, der außerhalb der udev-Verarbeitungspipeline läuft. So bleibt die eigentliche udev-Regel kurz und schnell, während die eigentliche Arbeit asynchron in einem separaten Prozess erledigt wird.
# Falsch: blockiert die udev Verarbeitung
# RUN+="/usr/local/bin/backup-new-disk.sh"
# Richtig: startet einen unabhaengigen, nicht blockierenden Service
RUN+="/usr/bin/systemd-run --no-block /usr/local/bin/backup-new-disk.sh"
7. Zusammenspiel von udev und systemd Device-Units
systemd erzeugt automatisch eine sogenannte Device-Unit für jedes von udev erkannte Gerät, sofern es über eine SYSFS-Eigenschaft namens SYSTEMD_WANTS oder eine passende Regel dafür markiert ist. Andere systemd-Units können diese Device-Unit dann in ihrer Requires= oder After= Direktive referenzieren und starten erst, wenn das entsprechende Gerät tatsächlich verfügbar ist.
Dieses Muster ist besonders für Storage relevant: Ein Mount-Unit für ein externes Backup-Volume kann über Requires=dev-disk-by\x2did-... so konfiguriert werden, dass systemd automatisch wartet, bis das Gerät von udev erkannt und benannt wurde, statt beim Boot mit einem Fehler abzubrechen, weil das Gerät noch nicht bereitsteht.
8. Praxisbeispiel: Persistente Namen für Netzwerkkarten setzen
Server mit mehreren Netzwerkkarten leiden unter demselben Grundproblem wie Storage-Geräte: Der vom Kernel vergebene Name wie eth0 oder eth1 hängt von der Erkennungsreihenfolge beim Boot ab und kann sich nach einem Kernel-Update oder dem Hinzufügen einer zusätzlichen Karte plötzlich ändern. Moderne Distributionen setzen deshalb standardmäßig auf vorhersagbare Namen wie enp3s0, die aus der physischen PCI-Position der Karte abgeleitet werden und stabil bleiben, solange die Hardware nicht umgesteckt wird.
Für Fälle, in denen selbst diese vorhersagbaren Namen nicht ausreichen, etwa weil zwei baugleiche Karten anhand ihrer Funktion im Netzwerk klar benannt werden sollen, erlaubt eine eigene udev-Regel eine noch gezieltere Zuordnung anhand der MAC-Adresse. So lässt sich etwa die Karte für das interne Storage-Netz zuverlässig storage0 nennen, unabhängig davon, welchen Namen der Kernel selbst vergeben hätte.
# /etc/udev/rules.d/71-net-storage-interface.rules
# Netzwerkkarte anhand der MAC Adresse eindeutig benennen
SUBSYSTEM=="net", ACTION=="add", ATTR{address}=="00:1a:2b:3c:4d:5e", \
NAME="storage0"
# Aktuelle Zuordnung von Namen zu MAC Adressen pruefen
ip -o link show
9. Best Practices und Debugging im laufenden Betrieb
Jede eigene Regel sollte zunächst mit möglichst spezifischen Match-Keys geschrieben werden, um unerwartete Treffer bei anderen Geräten zu vermeiden. Ein zu allgemeiner Match wie ausschließlich SUBSYSTEM=="block" ohne weitere Einschränkung trifft potenziell jede Festplatte im System und kann unbeabsichtigt bestehende Regeln überschreiben oder Konflikte erzeugen.
Für laufendes Debugging liefert journalctl -u systemd-udevd die Log-Ausgaben des udev-Daemons selbst, während udevadm monitor in Echtzeit zeigt, welche Uevents überhaupt eintreffen. Diese Kombination macht sichtbar, ob ein Problem tatsächlich an der eigenen Regel liegt oder ob das erwartete Uevent vom Kernel schlicht nie ausgelöst wird.
| Key | Typ | Bedeutung | Beispiel |
|---|---|---|---|
| KERNEL== | Match | Vom Kernel vergebener Gerätename | KERNEL=="sd?" |
| SUBSYSTEM== | Match | Geräteklasse wie block oder net | SUBSYSTEM=="net" |
| ATTR{name}== | Match | Attributwert aus sysfs | ATTR{idVendor}=="046d" |
| SYMLINK+= | Assign | Zusätzlichen Gerätepfad anlegen | SYMLINK+="disk/backup" |
| RUN+= | Assign | Externes Programm oder Service starten | RUN+="/usr/bin/systemd-run ..." |
Mironsoft
Server-Administration, Docker-Hosts und Performance-Tuning
Linux-Server, die niemand im Team richtig versteht?
Wir übernehmen Setup, Absicherung und Performance-Tuning von Linux-Servern und Docker-Hosts für Magento-Deployments, dokumentiert und nachvollziehbar statt gewachsen und unklar.
Server-Audit
Bestehende Server-Konfiguration auf Sicherheitslücken und Performance-Bremsen prüfen.
Docker-Host-Setup
Produktionsreife Docker-Umgebungen für Magento sauber aufsetzen und absichern.
Monitoring & Tuning
Ressourcenverbrauch messen und Systemd, Kernel und Dienste gezielt optimieren.
10. Zusammenfassung
udev-Regeln
Regelverzeichnis
/etc/udev/rules.d, Vorrang vor Standardregeln
Kernbefehl
udevadm test zur Simulation ohne Systemänderung
Häufigster Anwendungsfall
Persistente Namen für Storage über Seriennummer
Größter Fallstrick
Blockierende RUN+= Aufrufe statt systemd-run