Pourquoi les événements inotify se déclenchent plus d'une fois

13

Cette question découle d'une autre que j'avais posée sur Stackoverflow . J'utilise Watcher - les mêmes problèmes s'appliquent à Incron - pour surveiller un dossier et ses dossiers enfants pour les modifications et écarter silencieusement ces modifications vers Dropbox.

Je surveille l' write_closeévénement - IN_CLOSE_WRITE- dans ce but. À l'origine, je regardais l' modifyévénement, c'est-à-dire IN_MODIFY. Bien que cela ait fonctionné, j'ai constaté que lors de l'écriture de gros fichiers, il se déclencherait plus d'une fois. Cela semblait juste, alors je suis passé à IN_CLOSE_WRITEcar je pensais qu'il était raisonnablement juste de supposer que pour un fichier donné, cela ne se produirait qu'une seule fois.

Cependant, ce n'est pas le cas. Même pour un très petit fichier texte - un seul caractère - créé dans Nano, l'événement se produit deux fois. Au mieux, cela peut entraîner un trafic inutile lorsque le même fichier est synchronisé deux fois sur Dropbox. Dans mon propre cas, cela conduit à un désastre car lors du premier événement, j'effectue la synchronisation, puis je supprime le fichier côté serveur. Le résultat - lors du deuxième événement, le fichier latéral Dropbox devient un fichier de 0 octet.

Je traite cela pour l'instant en faisant dormir mon script de synchronisation pendant 10 secondes avant de faire quoi que ce soit d'autre, puis je vérifie que le fichier en question existe toujours avant d'essayer la synchronisation Dropbox. Cela fonctionne car à la deuxième itération, le fichier est manquant et le script se termine juste.

Cela semble au mieux hackish. Peut-être pas un mauvais hack mais je préférerais comprendre - pourquoi même l' IN_CLOSE_WRITEévénement se produit-il plus d'une fois?


Quelques informations supplémentaires

  • Vérifiez qu'il n'y a pas plusieurs instances de watcher en cours d'exécution.

Sortie de ps ax|grep watcher.py

23880 ?        Sl     0:01 python /usr/local/bin/watcher.py restart
24977 pts/0    S+     0:00 grep --color=auto watcher.py

Le système de fichiers est ext4. Je dois mentionner que j'ai rencontré exactement le même problème avec Incron. Je démarre le démon Watcher à partir d'un script batch exécuté via /etc/rc2.d. Incron OTH démarre sans aucun problème de ma part via son apt-get install incroninstallation par défaut .


L'essence de mon watcher.inidossier est illustrée ci-dessous.

[DEFAULT]
logfile=/var/log/watcher.log
pidfile=/var/run/watcher.pid

[job1]
watch=/path/to/watch

events=write_close
excluded=
recursive=true
autoadd=true

command=/home/datastore.php $filename

J'ai réduit le datastore.phpscript à l'essentiel pour vérifier qu'il est déclenché deux fois sans aucun de mon code de téléchargement + suppression de source Dropbox désordonné.

#! /usr/bin/php
<?php
file_put_contents('/tmp/watcher',$argv[1],FILE_APPEND);

?>

J'ai ensuite créé un petit fichier sur le chemin en question puis examiné /tmp/watcher. Le problème persiste - le fichier contient toujours deux entrées successives pour $argv[1].

DroidOS
la source
1
J'ai essayé de nombreuses variantes, mais je n'arrive pas à dupliquer votre problème avec plusieurs cuissons IN_CLOSE_WRITE. Tout ce que j'ai fait provoque une seule sortie inotify. Je vais continuer d'essayer des choses. Mais jusqu'à présent, seules des questions. Quel système de fichiers? Ext4? Autre?
lornix
@lornix - veuillez voir les modifications apportées à ma question. Le système de fichiers est ext4et je suis raisonnablement sûr de ne pas avoir deux instances de Watcher en cours d'exécution. J'ai rencontré le même problème avec Incron.
DroidOS
Vous avez dit: «J'effectue la synchronisation, puis je supprime le fichier côté serveur». Cette suppression déclenche-t-elle le deuxième événement? Pouvez-vous désactiver la deleteroutine et réessayer?
Germar
@Germar - voir la modification de ma question. Même avec le script de synchronisation sans synchronisation réelle et sans unlinkproblème, le problème persiste
DroidOS
Désolé, plutôt par manque d'idées, je ne peux reproduire le problème sur aucune de mes machines. Je reçois un événement, pas plus. Quelque chose d'autre est impliqué, quelque chose de non mentionné. Avez-vous installé un antivirus? quelque chose comme ça?
lornix

Réponses:

1

Je ne suis pas sûr, mais très probablement le premier write_close y écrit des attributs de fichier, comme le temps de création, et seulement après cela, il écrit des données réelles. En fait, rsync crée un fichier temporaire et lorsque tout est fait, il déplace le fichier temporaire vers le fichier réel dans le même dossier, il est donc facile de contrôler qu'il a été normalement créé lorsque vous utilisez rsync, et déplacer est une opération atomique. D'un autre côté, il y a quelque chose de calle one in inify, probablement que l'utilisation de cela peut déclencher quelque chose sur le premier message de modification, et comme vous l'avez suggéré de dormir pendant une durée raisonnable avant de commencer l'opération. Je suis en train de creuser cela maintenant et je mettrai à jour quand je trouverai quelque chose de nouveau. /superuser/1133642/traceing-the-moment-when-file-is-completely-copied-to-samba-share-with-inotify

Edik Mkoyan
la source
Vous avez peut-être bien mis le doigt sur quelque chose de tout à fait valable ici. Cela nécessitera une enquête. Merci pour le conseil. Je reviendrai dans le cas où je trouverais que c'est en quelque sorte un problème.
DroidOS
Je ne pense pas qu'ATTRIB ajoute quoi que ce soit au fichier lui-même, j'avais tort.
Edik Mkoyan
0

Je n'ai pas assez de représentants pour poster ceci en tant que commentaire, mais êtes-vous sûr que des fichiers temporaires, éventuellement cachés, ne sont pas créés? J'ai eu un problème similaire avec le inotifywaitdéclenchement plusieurs fois, mais j'ai réalisé que c'était parce que vim créerait un fichier .swp lors de l'édition, ce qui déclencherait un événement lors de la fermeture. Il récupérerait également l'événement de fermeture du fichier d'origine.

Il semble que vous remarquiez l'événement qui déclenche plusieurs fichiers sur le même fichier, ce qui n'est pas quelque chose que j'ai pu reproduire - cela ne se produirait qu'une fois pour le fichier temporaire et une fois pour l'original.

J'ai essayé un test rapide avec nano et je ne pense pas que cela crée un fichier temporaire (du moins pour la casse de quelques caractères), mais y a-t-il autre chose dans votre configuration qui pourrait s'appuyer sur un comportement similaire?

neocpp
la source
Merci pour vos suggestions. J'ai rencontré le problème multiple inotify même lorsque je crée un fichier 1 octet très trivial avec Nano - ou même en redirigeant simplement un seul caractère de la console dans un fichier. La «solution» que j'ai décrite dans ma question initiale me permet de continuer pour l'instant. Cependant, à plus long terme, la seule solution dont je dispose pour reconstruire mon serveur à partir de zéro pour identifier le moment où l'erreur commence - ma configuration avec Incron, Watcher (au fait, c'est arrivé quand je venais d'Incron), MariaDB, Nginx, Redis, Memcached ... n'est pas exactement "simple".
DroidOS
Au cas où, revérifiez si vous ne surveillez pas deux fois le même dossier. Si ce n'est pas le cas, par exemple, lorsque je copie un fichier sur le partage samba via le client os x samba, cela se produit. Create, close_write, delete, create, close_write. Je résous donc mon problème en surveillant la première modification du fichier avec ce répertoire IN_MODIFY, IN_ONESHOT /. Les commandes sleep someTime oneshot font la chose.
Edik Mkoyan