fsnotify ist eine Dateisystem-Benachrichtigungs-Bibliothek, die in Go geschrieben wurde und Änderungen an Dateien und Verzeichnissen im Dateisystem überwacht und die Anwendung benachrichtigt, wenn Änderungen auftreten. Es unterstützt plattformübergreifenden Betrieb und kann auf verschiedenen Betriebssystemen wie Linux, macOS und Windows ausgeführt werden. fsnotify nutzt die Dateisystembenachrichtigungsmechanismen verschiedener Betriebssysteme, z. B. inotify unter Linux, FSEvents unter macOS und ReadDirectoryChangesW unter Windows.
Es erfordert die Verwendung von Go 1.17 oder neueren Versionen. Die vollständige Dokumentation finden Sie unter https://pkg.go.dev/github.com/fsnotify/fsnotify.
Unterstützung für verschiedene Betriebssysteme:
Backend | Betriebssystem | Status |
---|---|---|
inotify | Linux | Unterstützt |
kqueue | BSD, macOS | Unterstützt |
ReadDirectoryChangesW | Windows | Unterstützt |
FEN | illumos | Unterstützt |
fanotify | Linux 5.9+ | Noch nicht unterstützt |
AHAFS | AIX | AIX-Zweig; Experimentelles Feature aufgrund fehlender Betreuer und Testumgebung |
FSEvents | macOS | Erfordert Unterstützung durch x/sys/unix |
USN Journals | Windows | Erfordert Unterstützung durch x/sys/windows |
Polling | Alle | Noch nicht unterstützt |
Android und Solaris, die Linux und illumos enthalten sollten, wurden noch nicht getestet.
Anwendungsfälle
Die Anwendungsfälle von fsnotify umfassen unter anderem folgende Situationen:
- Echtzeit-Dateisynchronisation: fsnotify kann Änderungen im Dateisystem in Echtzeit überwachen und eignet sich somit zur Implementierung einer Echtzeit-Dateisynchronisation. Wenn Änderungen in der Quelldatei auftreten, können die Änderungen sofort auf die Zieldatei synchronisiert werden, um die Konsistenz der Dateien zu gewährleisten.
- Automatisierter Build: fsnotify kann Änderungen im Quellcode des Projekts und in Abhängigkeitsdateien überwachen und Build-Befehle auslösen, wenn Änderungen auftreten, wodurch eine automatisierte Erstellung erreicht wird. Dies kann Zeit und Aufwand für manuelle Build-Prozesse sparen und die Entwicklungseffizienz verbessern.
- Dateisicherung: fsnotify kann Änderungen an Dateien oder Verzeichnissen, die gesichert werden müssen, überwachen und bei Änderungen eine sofortige Sicherung initiieren. Dies gewährleistet die Sicherheit von Daten und verhindert Datenverlust aufgrund von Dateiverlust oder Beschädigung.
- Echtzeit-Protokollüberwachung: fsnotify kann Operationen wie Erstellung, Änderung und Löschung von Protokolldateien überwachen und bei Änderungen in Protokolldateien Log-Überwachungsprogramme auslösen, um Änderungen im Protokollinhalt effektiv in Echtzeit zu überwachen.
- Dateisystem-Sicherheitsüberwachung: fsnotify kann Sicherheitsereignisse im Dateisystem überwachen, wie z. B. Dateizugriff, Änderung und Löschung. Dadurch kann das Dateisystem auf Sicherheitsereignisse überwacht werden, um unsichere Ereignisse zeitnah zu identifizieren und aufzuzeichnen.
Verwendungsbeispiel
Ein einfaches Beispiel:
package main
import (
"log"
"github.com/fsnotify/fsnotify"
)
func main() {
// Erstelle einen neuen Watcher.
watcher, err := fsnotify.NewWatcher()
if err != nil {
log.Fatal(err)
}
defer watcher.Close()
// Starte das Lauschen auf Ereignisse.
go func() {
for {
select {
case event, ok := <-watcher.Events:
if !ok {
return
}
log.Println("Ereignis:", event)
if event.Has(fsnotify.Write) {
log.Println("Geänderte Datei:", event.Name)
}
case err, ok := <-watcher.Errors:
if !ok {
return
}
log.Println("Fehler:", err)
}
}
}()
// Füge den Pfad hinzu, der überwacht werden soll.
err = watcher.Add("/tmp")
if err != nil {
log.Fatal(err)
}
// Blockiere die Haupt-Goroutine.
<-make(chan struct{})
}
Weitere Beispiele finden Sie in cmd/fsnotify und können mit dem folgenden Befehl ausgeführt werden:
% go run ./cmd/fsnotify
Weitere ausführliche Dokumentation finden Sie in godoc: https://pkg.go.dev/github.com/fsnotify/fsnotify
Häufig gestellte Fragen
Wird die Überwachung fortgesetzt, wenn die Datei in ein anderes Verzeichnis verschoben wird?
Nein, es sei denn, Sie überwachen den Ort, an den sie verschoben wird.
Überwacht es Unterverzeichnisse?
Nein, Sie müssen für jedes Verzeichnis, das Sie überwachen möchten, eine Überwachung hinzufügen (eine rekursive Überwachung ist geplant: #18).
Muss ich gleichzeitig die Fehler- und Ereigniskanäle in einem Goroutine überwachen?
Ja. Sie können select
verwenden, um aus beiden Kanälen in derselben Goroutine zu lesen (Sie müssen nicht für jeden Kanal separat eine Goroutine starten; siehe das Beispiel).
Warum funktionieren Benachrichtigungen nicht auf NFS, SMB, FUSE, /proc oder /sys?
fsnotify erfordert Unterstützung vom zugrunde liegenden Betriebssystem, um zu funktionieren. Die aktuellen NFS- und SMB-Protokolle bieten keine Netzwerkunterstützung für Dateibenachrichtigungen, und auch die virtuellen Dateisysteme /proc und /sys bieten keine Unterstützung.
Dies könnte durch die Verwendung eines Polling-Watchers behoben werden (#9), aber dies wurde noch nicht umgesetzt.
Warum erhalte ich viele Chmod-Ereignisse?
Einige Programme können eine große Anzahl von Attributänderungen generieren, wie z.B. Spotlight auf macOS, Antivirenprogramme, Backup-Anwendungen und einige andere bekannte Anwendungen. Im Allgemeinen ist es oft sinnvoll, Chmod-Ereignisse zu ignorieren, da sie häufig nutzlos sind und Probleme verursachen können.
Spotlight-Indizierungen auf macOS können mehrere Ereignisse verursachen (siehe #15). Eine vorübergehende Lösung besteht darin, Ihre Ordner zu den Spotlight-Privatsphäre-Einstellungen hinzuzufügen, bis wir eine native FSEvents-Implementierung haben (siehe #11).
Das Überwachen von Dateien funktioniert nicht gut
Im Allgemeinen wird nicht empfohlen, einzelne Dateien (statt Verzeichnisse) zu überwachen, da viele Programme, insbesondere Editoren, Dateien atomar aktualisieren: Es wird in eine temporäre Datei geschrieben und dann an den Zielort verschoben, wodurch die originale Datei überschrieben wird (oder eine Variante davon). Die Überwachung der ursprünglichen Datei geht nun verloren, da die Datei nicht mehr existiert.
Ein Stromausfall oder ein Absturz führt somit nicht zu einer halbgeschriebenen Datei.
Überwachen Sie das übergeordnete Verzeichnis und verwenden Sie Event.Name
, um die Dateien zu filtern, die Sie nicht interessieren. Ein Beispiel finden Sie in cmd/fsnotify/file.go
.
Hinweise für spezifische Plattformen
Linux
Wenn eine Datei gelöscht wird, wird das REMOVE-Ereignis erst ausgegeben, wenn alle Dateideskriptoren geschlossen sind; zu diesem Zeitpunkt wird ein CHMOD-Ereignis ausgegeben:
fp := os.Open("Datei")
os.Remove("Datei") // CHMOD
fp.Close() // REMOVE
Dies ist das Ereignis, das von inotify gesendet wird, daher sollten nicht zu viele Änderungen vorgenommen werden.
Die sysctl-Variable fs.inotify.max_user_watches
gibt die maximale Anzahl von Überwachungen pro Benutzer an, und fs.inotify.max_user_instances
gibt die maximale Anzahl von inotify-Instanzen pro Benutzer an. Jeder erstellte Watcher ist eine "Instanz", und jeder hinzugefügte Pfad ist eine "Überwachung".
Diese Informationen finden sich auch in /proc
mit den Pfaden /proc/sys/fs/inotify/max_user_watches
und /proc/sys/fs/inotify/max_user_instances
.
Um sie zu erhöhen, können Sie sysctl
verwenden oder die Werte in die Proc-Datei schreiben:
sysctl fs.inotify.max_user_watches=124983
sysctl fs.inotify.max_user_instances=128
Um die Änderungen nach einem Neustart wirksam werden zu lassen, bearbeiten Sie /etc/sysctl.conf
oder /usr/lib/sysctl.d/50-default.conf
(die Details können je nach Linux-Distribution variieren, bitte konsultieren Sie die Dokumentation Ihrer Distribution):
fs.inotify.max_user_watches=124983
fs.inotify.max_user_instances=128
Wenn das Limit erreicht ist, treten "No space left on device" oder "Too many open files"-Fehler auf.
kqueue (macOS, alle BSD-Systeme)
kqueue erfordert das Öffnen eines Dateideskriptors für jede beobachtete Datei; daher erreichen Sie auf diesen Plattformen die systemweite "maximum open files" Grenze schneller.
Sie können die sysctl-Variablen kern.maxfiles
und kern.maxfilesperproc
verwenden, um die maximale Anzahl von offenen Dateien zu kontrollieren.