fsnotify est une bibliothèque de notification du système de fichiers écrite en Go. Elle peut surveiller les changements apportés aux fichiers et répertoires du système de fichiers et informer l'application lorsque des changements se produisent. Elle prend en charge le fonctionnement multiplateforme et peut s'exécuter sur différents systèmes d'exploitation, tels que Linux, macOS et Windows. fsnotify utilise les mécanismes de notification du système de fichiers des différents systèmes d'exploitation, tels qu'inotify sur Linux, FSEvents sur macOS et ReadDirectoryChangesW sur Windows.
Elle nécessite l'utilisation de Go 1.17 ou de versions ultérieures ; la documentation complète peut être consultée à l'adresse https://pkg.go.dev/github.com/fsnotify/fsnotify
Prise en charge de différents systèmes d'exploitation :
Backend | Système d'exploitation | Statut |
---|---|---|
inotify | Linux | Pris en charge |
kqueue | BSD, macOS | Pris en charge |
ReadDirectoryChangesW | Windows | Pris en charge |
FEN | illumos | Pris en charge |
fanotify | Linux 5.9+ | Pas encore pris en charge |
AHAFS | AIX | Branche AIX ; Caractéristique expérimentale en raison du manque de mainteneurs et d'environnement de test |
FSEvents | macOS | Nécessite le support x/sys/unix |
Journaux USN | Windows | Nécessite le support x/sys/windows |
Scrutage | Tous | Pas encore pris en charge |
Android et Solaris, qui devraient inclure Linux et illumos, n'ont pas encore été testés.
Cas d'utilisation
Les cas d'utilisation de fsnotify comprennent, mais ne se limitent pas à, les situations suivantes :
- Synchronisation de fichiers en temps réel : fsnotify peut surveiller les changements dans le système de fichiers en temps réel, ce qui le rend adapté à la mise en œuvre de la synchronization de fichiers en temps réel. Lorsque des changements se produisent dans le fichier source, les modifications peuvent être immédiatement synchronisées vers le fichier cible, assurant ainsi la cohérence des fichiers.
- Construction automatisée : fsnotify peut surveiller les modifications apportées au code source du projet et aux fichiers de dépendances, déclenchant des commandes de construction lorsque des changements se produisent, ce qui permet d'atteindre une construction automatisée. Cela peut économiser du temps et des efforts de construction manuelle et améliorer l'efficacité du développement.
- Sauvegarde de fichiers : fsnotify peut surveiller les changements apportés aux fichiers ou répertoires devant être sauvegardés et lancer une sauvegarde immédiate lorsque des changements se produisent. Cela garantit la sécurité des données et empêche la perte de données due à la perte ou à la détérioration des fichiers.
- Surveillance de logs en temps réel : fsnotify peut surveiller des opérations telles que la création, la modification et la suppression de fichiers journaux, déclenchant des programmes de surveillance de logs lorsque des changements se produisent dans les fichiers journaux, permettant ainsi de surveiller efficacement les modifications du contenu des logs en temps réel.
- Surveillance de la sécurité du système de fichiers : fsnotify peut surveiller les événements de sécurité dans le système de fichiers, tels que l'accès, la modification et la suppression de fichiers. Cela permet la surveillance de la sécurité du système de fichiers, identifiant rapidement et enregistrant les événements non sécurisés.
Exemple d'utilisation
Un exemple de base :
package main
import (
"log"
"github.com/fsnotify/fsnotify"
)
func main() {
// Créer un nouveau watcher.
watcher, err := fsnotify.NewWatcher()
if err != nil {
log.Fatal(err)
}
defer watcher.Close()
// Commencer à écouter les événements.
go func() {
for {
select {
case event, ok := <-watcher.Events:
if !ok {
return
}
log.Println("Event:", event)
if event.Has(fsnotify.Write) {
log.Println("Fichier modifié:", event.Name)
}
case err, ok := <-watcher.Errors:
if !ok {
return
}
log.Println("Erreur:", err)
}
}
}()
// Ajouter le chemin qui doit être surveillé.
err = watcher.Add("/tmp")
if err != nil {
log.Fatal(err)
}
// Bloquer le goroutine principale.
<-make(chan struct{})
}
D'autres exemples peuvent être trouvés dans cmd/fsnotify et peuvent être exécutés en utilisant la commande suivante :
% go run ./cmd/fsnotify
Une documentation plus détaillée peut être trouvée dans godoc : https://pkg.go.dev/github.com/fsnotify/fsnotify
Questions Fréquemment Posées
Est-ce que le fichier continuera d'être surveillé s'il est déplacé dans un autre répertoire ?
Non, à moins que vous ne surveilliez l'emplacement où il a été déplacé.
Est-ce qu'il surveille les sous-répertoires?
Non, vous devez ajouter une surveillance pour chaque répertoire que vous souhaitez surveiller (la surveillance récursive est prévue: #18).
Est-ce que je dois surveiller à la fois les canaux d'erreur et d'événement dans une goroutine simultanément?
Oui. Vous pouvez utiliser select
pour lire à partir des deux canaux dans la même goroutine (vous n'avez pas besoin de démarrer une goroutine séparément pour chaque canal; voir l'exemple).
Pourquoi les notifications ne fonctionnent-elles pas sur NFS, SMB, FUSE, /proc ou /sys?
fsnotify nécessite un support du système d'exploitation sous-jacent pour fonctionner. Les protocoles NFS et SMB actuels ne fournissent pas de support au niveau du réseau pour les notifications de fichier, et les systèmes de fichiers virtuels /proc et /sys ne fournissent pas non plus de support.
Cela pourrait être résolu en utilisant un observateur de type polling (#9), mais cela n'a pas encore été implémenté.
Pourquoi est-ce que je reçois de nombreux événements Chmod?
Certains programmes peuvent générer un grand nombre de modifications d'attributs, tels que Spotlight sur macOS, des programmes antivirus, des applications de sauvegarde, et quelques autres applications connues. En général, ignorer les événements Chmod est souvent la meilleure pratique car ils sont souvent inutiles et peuvent causer des problèmes.
L'indexation de Spotlight sur macOS peut entraîner de multiples événements (voir #15). Une solution temporaire consiste à ajouter vos dossiers aux Paramètres de confidentialité de Spotlight jusqu'à ce que nous disposions d'une implémentation native de FSEvents (voir #11).
La surveillance des fichiers ne fonctionne pas bien
Il n'est généralement pas recommandé de surveiller des fichiers individuels (plutôt que des répertoires) car de nombreux programmes, en particulier des éditeurs, mettront à jour les fichiers de manière atomique : ils écriront dans un fichier temporaire, puis le déplaceront à l'emplacement cible, écrasant le fichier original (ou une variante de celui-ci). Le suivi sur le fichier d'origine est maintenant perdu car le fichier n'existe plus.
Par conséquent, une panne de courant ou un plantage ne donnera pas un fichier partiellement écrit.
Surveillez le répertoire parent et utilisez Event.Name
pour filtrer les fichiers qui ne vous intéressent pas. Il y a un exemple dans cmd/fsnotify/file.go
.
Remarques pour des plates-formes spécifiques
Linux
Lorsqu'un fichier est supprimé, l'événement REMOVE ne sera pas émis tant que tous les descripteurs de fichier ne seront pas fermés ; à ce moment, un événement CHMOD sera émis :
fp := os.Open("file")
os.Remove("file") // CHMOD
fp.Close() // REMOVE
C'est l'événement envoyé par inotify, donc il ne devrait pas y avoir trop de modifications apportées à cela.
La variable sysctl fs.inotify.max_user_watches
spécifie le nombre maximal de surveillances par utilisateur, et fs.inotify.max_user_instances
spécifie le nombre maximal d'instances inotify par utilisateur. Chaque Watcher que vous créez est une "instance", et chaque chemin que vous ajoutez est une "surveillance".
Ces valeurs peuvent également être trouvées dans /proc
, avec les chemins /proc/sys/fs/inotify/max_user_watches
and /proc/sys/fs/inotify/max_user_instances
.
Pour les augmenter, vous pouvez utiliser sysctl
ou écrire les valeurs dans le fichier proc :
sysctl fs.inotify.max_user_watches=124983
sysctl fs.inotify.max_user_instances=128
Pour que les modifications prennent effet après un redémarrage, éditez /etc/sysctl.conf
ou /usr/lib/sysctl.d/50-default.conf
(les détails peuvent varier pour chaque distribution Linux, veuillez vous référer à la documentation de votre distribution) :
fs.inotify.max_user_watches=124983
fs.inotify.max_user_instances=128
Atteindre la limite entraînera des erreurs "Aucun espace disponible sur le dispositif" ou "Trop de fichiers ouverts".
kqueue (macOS, tous les systèmes BSD)
kqueue nécessite l'ouverture d'un descripteur de fichier pour chaque fichier observé ; par conséquent, si vous observez un répertoire contenant cinq fichiers, cela fait six descripteurs de fichier. Sur ces plates-formes, vous atteindrez plus rapidement la limite du "nombre maximal de fichiers ouverts" du système.
Vous pouvez utiliser les variables sysctl kern.maxfiles
and kern.maxfilesperproc
pour contrôler le nombre maximal de fichiers ouverts.