Dateisystem Events in Echtzeit überwachen
Ein Cron Job, der jede Minute ein Verzeichnis nach Änderungen durchsucht, verschwendet Ressourcen und reagiert trotzdem erst mit Verzögerung. Der Linux Kernel bietet mit inotify und dem mächtigeren fanotify zwei Event basierte Mechanismen, die Änderungen am Dateisystem sofort melden, ganz ohne Polling.
Inhaltsverzeichnis
- 1. Warum Polling nicht reicht
- 2. inotify Grundlagen: Watches, Events und inotifywait
- 3. fanotify Grundlagen und der Unterschied zu inotify
- 4. Watch Limits verstehen und tunen
- 5. Praxisbeispiel: Konfigurationsänderungen live erkennen
- 6. Praxisbeispiel: Upload Verzeichnis überwachen
- 7. fanotify für Zugriffskontrolle und Malware Scanning
- 8. systemd Path Units als betriebsfreundliche Alternative
- 9. Typische Fallstricke bei rekursiver Überwachung
- 10. Zusammenfassung
- 11. FAQ
1. Warum Polling nicht reicht
Ein klassischer Ansatz zur Überwachung eines Verzeichnisses besteht darin, in regelmäßigen Abständen per Cron Job oder Skript den Verzeichnisinhalt zu scannen und mit dem vorherigen Zustand zu vergleichen. Dieser Ansatz kostet unnötig CPU Zeit, selbst wenn sich nichts geändert hat, und liefert bestenfalls eine Reaktionszeit in der Größenordnung des Scan Intervalls, was für zeitkritische Anwendungsfälle wie das sofortige Erkennen einer manipulierten Konfigurationsdatei ungeeignet ist.
Der Linux Kernel löst dieses Problem mit zwei komplementären Schnittstellen: inotify, seit Kernel 2.6.13 verfügbar, meldet Änderungen an einzelnen Dateien und Verzeichnissen als Events an einen wartenden Prozess, während das mächtigere fanotify, seit Kernel 2.6.36 und in vollem Umfang seit 2.6.37, zusätzlich Zugriffsentscheidungen treffen und ganze Mounts statt einzelner Pfade überwachen kann.
2. inotify Grundlagen: Watches, Events und inotifywait
inotify arbeitet mit sogenannten Watches, die jeweils für eine bestimmte Datei oder ein bestimmtes Verzeichnis eingerichtet werden und dann Events wie IN_MODIFY, IN_CREATE, IN_DELETE oder IN_MOVED_TO an den überwachenden Prozess liefern. Jeder Watch bezieht sich explizit auf einen Pfad, weshalb die Überwachung eines Verzeichnisbaums mit vielen Unterordnern bedeutet, dass für jeden einzelnen Unterordner ein eigener Watch registriert werden muss, da inotify keine native Rekursion unterstützt.
Für Shell Skripte ist inotifywait aus dem inotify-tools Paket das praktischste Werkzeug, weil es die Low Level inotify API in eine einfache Kommandozeilenschnittstelle verpackt, die sich in Bash Skripten ohne eigenen C Code direkt verwenden lässt.
# inotify-tools installieren
apt install -y inotify-tools
# Ein Verzeichnis auf Aenderungs Events überwachen, Ausgabe pro Event
inotifywait -m -e modify,create,delete,move /etc/nginx/
3. fanotify Grundlagen und der Unterschied zu inotify
fanotify wurde ursprünglich für Antiviren Software und Zugriffskontrolle entwickelt und kann im Gegensatz zu inotify nicht nur Events melden, sondern bei entsprechender Konfiguration auch aktiv über sogenannte Permission Events entscheiden, ob ein Zugriff überhaupt erlaubt wird, bevor er tatsächlich stattfindet. Dieser Modus erfordert allerdings root Rechte beziehungsweise die Capability CAP_SYS_ADMIN, während einfache inotify Watches auch für unprivilegierte Prozesse nutzbar sind.
Ein weiterer wesentlicher Unterschied liegt im Geltungsbereich: fanotify kann mit dem Flag FAN_MARK_MOUNT oder FAN_MARK_FILESYSTEM einen kompletten Mount Punkt oder ein ganzes Dateisystem auf einmal überwachen, statt wie inotify einzelne Pfade explizit registrieren zu müssen, was fanotify für die Überwachung großer, sich dynamisch verändernder Verzeichnisstrukturen deutlich praktikabler macht.
# fanotify Beispiel mit dem CLI Werkzeug fatrace, zeigt Zugriffe systemweit
apt install -y fatrace
# Alle Dateizugriffe auf dem System live protokollieren
fatrace
4. Watch Limits verstehen und tunen
Jeder registrierte inotify Watch belegt Kernel Speicher, weshalb der Kernel standardmäßig ein Limit über fs.inotify.max_user_watches durchsetzt, das auf vielen Distributionen bei rund 8192 Watches pro Benutzer liegt. Wird dieses Limit überschritten, etwa weil ein Entwicklungswerkzeug oder ein Build System rekursiv jedes Verzeichnis inklusive node_modules überwacht, quittiert der Kernel weitere Watch Registrierungen mit dem Fehler ENOSPC, was in der Praxis oft als kryptischer Fehler in IDEs oder Dateisynchronisationstools auffällt.
Für Server mit vielen überwachten Verzeichnissen, etwa Konfigurationsmanagement Werkzeugen oder Log Aggregatoren, sollte das Limit deutlich angehoben werden. Ebenso relevant sind fs.inotify.max_user_instances, das die Anzahl gleichzeitig geöffneter inotify Instanzen pro Benutzer begrenzt, und fs.inotify.max_queued_events, das die Größe der Event Warteschlange pro Instanz festlegt und bei sehr aktiven Verzeichnissen zu Event Verlust führen kann, wenn es zu niedrig gesetzt ist.
# Aktuelle Limits anzeigen
sysctl fs.inotify.max_user_watches
sysctl fs.inotify.max_user_instances
sysctl fs.inotify.max_queued_events
# Limits dauerhaft erhoehen
cat >> /etc/sysctl.d/99-inotify.conf <<'EOF'
fs.inotify.max_user_watches = 524288
fs.inotify.max_user_instances = 1024
fs.inotify.max_queued_events = 65536
EOF
sysctl --system
5. Praxisbeispiel: Konfigurationsänderungen live erkennen
Ein häufiger Einsatzfall auf Servern ist die sofortige Reaktion auf Änderungen an sicherheitsrelevanten Konfigurationsdateien, etwa um bei einer unerwarteten Änderung an /etc/passwd oder einer Nginx Konfiguration umgehend einen Alarm auszulösen, statt auf den nächsten geplanten Audit Lauf zu warten. Ein einfaches Skript mit inotifywait im Endlosmodus reicht dafür bereits aus und lässt sich problemlos als systemd Service dauerhaft betreiben.
Für den produktiven Einsatz empfiehlt sich, das Skript nicht nur das rohe Event auszugeben, sondern zusätzlich Kontext wie den geänderten Dateinamen und einen Zeitstempel in ein Log oder direkt an ein Monitoring System weiterzugeben, damit spätere forensische Analysen nachvollziehbar bleiben.
#!/usr/bin/env bash
# scripts/watch-config-changes.sh: Config Änderungen sofort melden
set -euo pipefail
inotifywait -m -e modify,attrib,move,create,delete \
/etc/passwd /etc/nginx/nginx.conf /etc/ssh/sshd_config |
while read -r path event file; do
echo "$(date -Iseconds) ALERT: $event auf $path$file" \
| tee -a /var/log/config-watch.log
# Hier liesse sich zusätzlich ein Alert an Monitoring senden
done
6. Praxisbeispiel: Upload Verzeichnis überwachen
Für Anwendungen, die hochgeladene Dateien asynchron weiterverarbeiten müssen, etwa das Erzeugen von Thumbnails nach einem Produktbild Upload, bietet sich eine ereignisgesteuerte Verarbeitung mit inotify anstelle eines periodischen Scans an. Statt jede Minute das gesamte Upload Verzeichnis zu durchsuchen, wird die Verarbeitung exakt dann angestoßen, wenn eine neue Datei vollständig geschrieben wurde.
Wichtig ist dabei die Wahl des richtigen Events: IN_CLOSE_WRITE feuert erst, wenn eine Datei nach dem Schreiben geschlossen wird, und ist damit deutlich zuverlässiger als IN_CREATE, das bereits beim Anlegen der Datei auslöst, lange bevor der eigentliche Upload Vorgang abgeschlossen ist, was sonst zu einer Verarbeitung unvollständiger Dateien führen kann. Alternativ übernimmt das Daemon Werkzeug incrond diese Aufgabe konfigurationsbasiert, ohne dass ein eigenes Skript dauerhaft laufen muss.
# Erst reagieren, wenn eine Datei vollstaendig geschrieben und geschlossen wurde
inotifywait -m -e close_write --format '%f' /var/www/media/upload/ |
while read -r filename; do
/usr/local/bin/generate-thumbnail.sh "/var/www/media/upload/$filename"
done
# Alternative mit incrond: Eintrag in /etc/incron.d/media-upload
# /var/www/media/upload IN_CLOSE_WRITE /usr/local/bin/generate-thumbnail.sh $@/$#
7. fanotify für Zugriffskontrolle und Malware Scanning
Über Permission Events kann fanotify entscheiden, ob ein Dateizugriff tatsächlich stattfinden darf, bevor der eigentliche Systemaufruf zurückkehrt, ein Verhalten, das inotify grundsätzlich nicht bietet, da inotify Events immer erst nach der abgeschlossenen Operation ausgeliefert werden. Antiviren Lösungen nutzen genau diesen Mechanismus, um Dateien im Moment des Öffnens zu scannen und den Zugriff bei einem Fund zu blockieren, bevor Schadcode überhaupt ausgeführt werden kann.
Diese Fähigkeit macht fanotify allerdings deutlich komplexer in der Handhabung als inotify und erfordert sorgfältiges Timeout Handling, weil ein hängender Scan Prozess sonst den gesamten Dateizugriff auf dem überwachten Mount blockieren würde. Für die meisten administrativen Überwachungsaufgaben ohne aktive Zugriffskontrolle bleibt daher inotify die einfachere und ausreichende Wahl.
8. systemd Path Units als betriebsfreundliche Alternative
Wer inotify Überwachung dauerhaft und produktionsreif betreiben will, sollte prüfen, ob eine systemd Path Unit statt eines selbst geschriebenen Dauerlauf Skripts die passendere Lösung ist. Eine Path Unit definiert deklarativ, auf welchen Pfad reagiert werden soll, und startet beim Auslösen einen zugehörigen systemd Service, wobei intern ebenfalls inotify zum Einsatz kommt, allerdings vollständig vom Init System verwaltet.
Der praktische Vorteil liegt in der Integration: Neustart bei Absturz, strukturiertes Logging über journalctl und Abhängigkeiten zu anderen Services lassen sich mit den ohnehin vorhandenen systemd Bordmitteln abbilden, statt diese Funktionalität in einem eigenen Bash Skript nachzubauen. Für einfache Trigger Muster, etwa das Neuladen eines Dienstes nach einer Konfigurationsänderung, ist eine Path Unit oft die robustere und wartungsärmere Wahl gegenüber einem eigenen inotifywait Dauerlauf.
# /etc/systemd/system/nginx-config-watch.path
[Unit]
Description=Watch nginx config for changes
[Path]
PathModified=/etc/nginx/nginx.conf
[Install]
WantedBy=multi-user.target
# /etc/systemd/system/nginx-config-watch.service
[Unit]
Description=Reload nginx after config change
[Service]
Type=oneshot
ExecStart=/usr/sbin/nginx -s reload
9. Typische Fallstricke bei rekursiver Überwachung
Der häufigste Fallstrick ist die fehlende native Rekursion von inotify: Ein neu angelegtes Unterverzeichnis wird nicht automatisch überwacht, sofern das Skript nicht explizit auf IN_CREATE Events für Verzeichnisse reagiert und dynamisch neue Watches registriert. Werkzeuge wie inotifywait -r lösen das komfortabel, indem sie beim Start rekursiv Watches für den gesamten Baum anlegen, was bei sehr großen Bäumen aber schnell an das watch Limit stößt.
Ein weiterer Fallstrick betrifft Verzeichnisse wie node_modules oder große Vendor Verzeichnisse, deren rekursive Überwachung tausende Watches gleichzeitig belegt und damit das Limit für andere Anwendungen auf demselben Server aufbraucht. Für solche Fälle sind gezielte, nicht rekursive Watches auf die tatsächlich relevanten Verzeichnisse meist die bessere Wahl als eine pauschale rekursive Überwachung des gesamten Baums.
| Merkmal | inotify | fanotify |
|---|---|---|
| Rechte für Basisnutzung | Auch ohne root nutzbar | Permission Events erfordern root oder CAP_SYS_ADMIN |
| Geltungsbereich | Einzelne Pfade, keine native Rekursion | Ganzer Mount oder Dateisystem möglich |
| Zugriffsentscheidung vor Ausführung | Nicht möglich, nur nachträgliche Meldung | Möglich über Permission Events |
| Typisches Werkzeug | inotifywait, incrond | fatrace, Antiviren Software |
| Ressourcenbedarf pro Watch | Ein Watch pro überwachtem Pfad | Ein Mark pro Mount oder Dateisystem |
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
inotify und fanotify
Kernunterschied
inotify meldet Events, fanotify kann Zugriffe zusätzlich blockieren
Wichtiges Tuning
fs.inotify.max_user_watches bei vielen überwachten Pfaden anheben
Praxiswerkzeug
inotifywait aus inotify-tools für Shell Skripte
Größter Fallstrick
Keine native Rekursion, neue Unterverzeichnisse brauchen eigenen Watch