GNU/Linux >> Tutoriels Linux >  >> Linux

Réflexions sur la surveillance des modifications de fichiers avec Linux sur le réseau

La surveillance d'un répertoire pour les modifications avec Linux est possible grâce au mécanisme bien connu inotify. Avec inotify, il est possible de définir une surveillance sur un répertoire, de le configurer pour surveiller les événements sur le contenu et vous recevrez des messages sur un descripteur de fichier lorsque quelque chose se produit. Cela fonctionne parfaitement lorsque le répertoire se trouve sur un stockage local, comme un disque dur, un SSD ou une clé USB, mais cela ne suffit pas lorsque le répertoire se trouve sur un système de fichiers réseau lorsque le stockage se trouve sur un autre ordinateur. Un autre utilisateur travaillant dans le même répertoire, connecté via le même système de fichiers ou un autre, peut supprimer un fichier et la surveillance que vous avez configurée dessus ne sera pas notifiée.

Pourquoi est-ce ?

De par sa conception, inotify obtient le résultat d'une opération (comme mkdir ou chmod) mais le type de système de fichiers sur lequel se trouve la montre est inconnu (une boîte noire) à inotify. Le système de fichiers ne "sait" pas qu'une surveillance a été définie et ne peut donc pas prendre la bonne action, comme notifier l'hôte distant sur lequel quelqu'un souhaite surveiller un répertoire.

Tant que vous êtes le seul utilisateur, il n'y a pas de problème. Cela devient un problème lorsqu'il y a plus d'utilisateurs travaillant dans le répertoire que vous souhaitez surveiller.

Vous pouvez comparer ce comportement avec une bibliothèque publique. Lorsque vous êtes le seul utilisateur, vous pouvez savoir quels livres sont disponibles et lesquels ne le sont pas, car vous savez lesquels vous avez empruntés. Ce n'est plus possible lorsque vous n'êtes pas le seul utilisateur, il y a plus d'utilisateurs qui empruntent les livres.

Dans ce cas, quelqu'un dans la bibliothèque doit gérer ce qui est emprunté par n'importe quel utilisateur (ce qui est le cas habituel), et vous devez contacter cette personne pour savoir si un livre est disponible ou non. C'est comme demander à quelqu'un de vous informer lorsqu'un livre, qui n'est actuellement pas présent, est à nouveau disponible.

Maintenant, ce contact avec la bibliothèque pour vous informer ne fonctionne pas avec Linux, où bien sûr la bibliothèque est le stockage distant, et le serveur est "quelqu'un" qui travaille dans la bibliothèque.

Pour que cela fonctionne avec Linux, il faut que le serveur distant soit averti qu'une surveillance a été définie.

En fait, les systèmes de fichiers comme CIFS et les versions récentes de NFS contiennent le support de l'envoi d'une surveillance au serveur :pour CIFS sur la ligne 6438 de fs/cifs/cifssmb.c du noyau 4.1.2, le message SMB pour cela (NT_TRANSACT_NOTIFY_CHANGE) est commenté mais toujours présent. La raison de ce commentaire est que cela fonctionnait avec dnotify, qui n'est plus le système fsnotify par défaut pour Linux depuis longtemps.


Faire fonctionner le transfert de veilles sous Linux avec des systèmes de fichiers réseau et FUSE est possible via l'espace noyau.

Récemment, j'ai essayé d'implémenter ce "transfert de la montre vers le serveur" avec FUSE. J'ai dû patcher :

Le sous-système du noyau fsnotify, pour notifier au module du noyau FUSE qu'une surveillance a été définie ou supprimée sur un inode.

Le module noyau FUSE doit agir après avoir été informé par fsnotify. J'ai introduit un nouveau code d'opération
FUSE_FSNOTIFY que le module du noyau envoie au démon de l'espace utilisateur avec le numéro d'inode et le masque.

La bibliothèque FUSE pour recevoir et traiter l'appel FUSE_FSNOTIFY en appelant la bonne fonction du système de fichiers de l'espace utilisateur.

La bibliothèque FUSE pour recevoir et traiter les événements fs et les rapporter au VFS.

En regardant de plus près comment les choses fonctionnent, lorsque la montre a été définie par le système de fichiers de l'espace utilisateur sur son backend avec succès (notez qu'il est également possible qu'il réponde ENOSYS), le backend peut envoyer un événement sur la montre à tout moment, jusqu'à ce que le la montre est retirée. Que faire de cet événement ?

Un scénario possible :

Introduisez un opcode FUSE supplémentaire FUSE_FSNOTIFY_EVENT, traduisez le masque dans l'événement reçu du protocole backend en quelque chose que fsnotify comprend, et renvoyez-le au module FUSE en utilisant le nouvel opcode, l'inode de la montre, le nom de l'entrée, et le masque traduit. Le module FUSE à son tour l'envoie au sous-système fsnotify, qui informe les auditeurs (inotify et/ou fanotify), où l'information est fournie que l'événement est sur le backend. (un indicateur d'événement supplémentaire est requis, par exemple pour inotify le masque d'événement IN_REMOTE, pour fanotify FAN_REMOTE). C'est à l'auditeur que faire de cette information. Le VFS local peut ou non être déjà à jour.

Remarques :

Traduire un masque d'un backend en quelque chose que fsnotify comprend peut être très facile et pas si facile, selon l'événement. Les événements de base comme la création (ou la suppression) d'une entrée dans le répertoire surveillé sont simples (FS_CREATE et FS_DELETE resp.), le changement de propriétaire n'est pas si difficile non plus (FS_ATTRIB), mais quelque chose comme un attribut étendu (SMB utilise ceux-ci beaucoup) ne peuvent être traduits en quelque chose de générique que FS_ATTRIB.

Le module FUSE doit vérifier que la montre et/ou l'inode est toujours valide, et si le masque de la montre s'applique au masque d'événement.

Des bits de masque supplémentaires IN_REMOTE (pour inotify) et FAN_REMOTE (pour fanotify) sont requis.

La double information est à éviter. C'est délicat. Par exemple, la création d'un fichier dans le répertoire surveillé sur le même hôte que la surveillance. Lorsque cette opération réussit, cela provoquera un événement fsnotify FS_CREATE, et créera également un FS_CREATE | Événement FS_REMOTE, puisque l'opération est effectuée avec succès sur le backend, ce qui entraîne ce message (du backend→fuse library→FUSE kernel module→fsnotify subsystem→inotify et/ou fanotify).

Une façon de résoudre ce problème consiste à demander au backend de n'envoyer que des événements initiés par d'autres. Pour le backend, il est assez simple de comparer l'initiateur (hôte) d'un événement FS avec l'hôte établissant la connexion.

Une autre solution consiste à comparer l'événement signalé avec le cache local dans la bibliothèque de fusibles et le module FUSE. Avec l'exemple de création d'un fichier, la bibliothèque (et le module FUSE) doit vérifier que l'entrée existe déjà dans le répertoire surveillé. Si ce n'est pas le cas, il n'est pas lancé par cet hôte. Pour une suppression, c'est similaire.

Pour d'autres événements, comme l'écriture d'un fichier ou le changement de propriétaire, cette méthode n'est pas suffisante, des informations supplémentaires sur ce qui a changé à distance (comme la nouvelle taille, le nouveau propriétaire) doivent figurer dans le message envoyé par l'hôte distant.

Si ces informations ne sont pas fournies par le backend, une autre solution consiste à faire en sorte que le démon responsable de la surveillance des événements FS au nom des clients maintienne un cache des événements locaux récents. Si un événement distant est signalé et qu'aucun équivalent local n'est trouvé dans le cache, il est initié par un autre hôte. Cela peut devenir délicat car les événements sont signalés en utilisant une connexion pour un certain utilisateur, d'autres utilisateurs peuvent ou non être autorisés à recevoir des événements. Et quelle sera la taille de ce cache ?

J'ai utilisé FUSE ci-dessus, je pense que c'est similaire pour d'autres systèmes de fichiers comme CIFS et NFS.

Oh et oui, il y a encore une autre option :il suffit d'interroger toutes les 5 secondes environ.

Stef Bon


Linux
  1. Vérifiez l'état du fichier sous Linux avec la commande stat

  2. Copiez et collez sur la ligne de commande Linux avec xclip

  3. surveillance des modifications de fichiers c++ linux

  4. Surveillance du niveau du microphone avec un outil de ligne de commande sous Linux

  5. Quel est le concept de création d'un fichier avec zéro octet sous Linux ?

Linux :Comment partager des fichiers sur un réseau local avec woof

Commande Linux watch avec exemples

Commande Linux WC avec exemples

Surveillance de la bande passante sous Linux avec Nethogs

Network Manager sur Linux avec des exemples

Sécurisez Linux avec le fichier Sudoers