¿Por qué los eventos de inotify se disparan más de una vez?

13

Esta pregunta surge de otra que había planteado en Stackoverflow . Estoy usando Watcher , los mismos problemas se aplican a Incron , para monitorear una carpeta y sus carpetas secundarias en busca de cambios y silenciar esos cambios en Dropbox.

Superviso el write_closeevento - IN_CLOSE_WRITE- con el propósito. Originalmente estaba viendo el modifyevento, es decir, IN_MODIFY. Si bien esto funcionó, descubrí que al escribir archivos grandes se dispararía más de una vez. Eso sonaba justo, así que cambié IN_CLOSE_WRITEya que sentí que era razonablemente justo suponer que para un archivo dado solo ocurriría una vez.

Sin embargo, este no es el caso. Incluso para un archivo de texto muy pequeño, solo un carácter, creado en Nano, el evento ocurre dos veces. En el mejor de los casos, esto puede generar tráfico innecesario cuando el mismo archivo se sincroniza en Dropbox dos veces. En mi propio caso conduce a un desastre ya que en el primer evento realizo la sincronización y luego elimino el archivo del lado del servidor. El resultado: en el segundo evento, el archivo lateral de Dropbox se convierte en un archivo de 0 bytes.

Estoy lidiando con esto por ahora haciendo que mi script de sincronización duerma por 10 segundos antes de hacer cualquier otra cosa y luego verifico que el archivo en cuestión aún exista antes de intentar la sincronización de Dropbox. Esto funciona porque en la segunda iteración falta el archivo y el script simplemente termina.

Esto suena hackear en el mejor de los casos. Quizás no sea un mal truco, pero preferiría entenderlo, ¿por qué incluso el IN_CLOSE_WRITEevento ocurre más de una vez?


Alguna información adicional

  • Verifique para asegurarse de que no haya varias instancias de observador en ejecución.

Salida 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

El sistema de archivos es ext4. Debo mencionar que he encontrado exactamente el mismo problema con Incron. Comienzo el demonio Watcher desde un script por lotes ejecutado a través de /etc/rc2.d. Incron OTH se inicia sin ningún problema por mí a través de su apt-get install incroninstalación predeterminada .


La esencia de mi watcher.iniarchivo se muestra a continuación.

[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

Reduje la datastore.phpsecuencia de comandos a lo esencial para verificar que se activa dos veces sin ninguno de mis desordenados carga de Dropbox + código de eliminación de fuente.

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

?>

Luego creé un pequeño archivo en la ruta en cuestión y luego lo examiné /tmp/watcher. El problema aún persiste: el archivo todavía tiene dos entradas sucesivas para $argv[1].

DroidOS
fuente
1
He intentado muchas variaciones, pero no puedo duplicar su problema con varios disparos IN_CLOSE_WRITE. Todo lo que he hecho causa una única salida de inotify. Voy a seguir intentando cosas. Pero hasta ahora, solo preguntas. ¿Qué sistema de archivos? Ext4? ¿Otro?
lornix
@lornix: vea las ediciones de mi pregunta. El sistema de archivos es ext4y estoy razonablemente seguro de que no tengo dos instancias de Watcher ejecutándose. Me he encontrado con el mismo problema con Incron.
DroidOS
Dijiste 'Realizo la sincronización y luego elimino el archivo del lado del servidor'. ¿Esta eliminación desencadena el segundo evento? ¿Puedes desactivar la deleterutina e intentarlo de nuevo?
Germar
@Germar: vea la edición de mi pregunta. Incluso con el script de sincronización sin sincronización real y sin unlinkproblemas, el problema persiste
DroidOS
Lo sentimos, más bien por ideas, no puedo reproducir el problema en ninguna de mis máquinas. Tengo un evento, no más. Algo más está involucrado, algo no mencionado. ¿Tienes antivirus instalado? ¿Cualquier cosa como eso?
lornix

Respuestas:

1

No estoy seguro, pero lo más probable es que el primer write_close escriba atributos de archivo en él, como el tiempo de creación, y solo después de eso escribe datos reales. De hecho, rsync crea un archivo temporal y cuando todo está hecho, mueve el archivo temporal al archivo real en la misma carpeta, por lo que es fácil de monitorear cuando se usa rsync, y mover es una operación atómica. Por otro lado, hay algo que se llama one shot en inotify, probablemente que al usar eso podemos activar algo en el primer mensaje de modificación, y como sugirió dormir durante un período de tiempo razonable antes de comenzar la operación. Estoy cavando esto ahora, y lo actualizaré cuando encuentre algo nuevo. /superuser/1133642/traceing-the-moment-when-file-is-completely-copied-to-samba-share-with-inotify

Edik Mkoyan
fuente
Puede que hayas señalado algo bastante válido aquí. Requerirá alguna investigación. Gracias por el consejo. Volveré a publicar en caso de que encuentre que esto es de alguna manera un problema.
DroidOS
No creo que ATTRIB agregue nada al archivo en sí, estaba equivocado.
Edik Mkoyan
0

No tengo suficiente representante para publicar esto como un comentario, pero ¿estás seguro de que no se crean archivos temporales, posiblemente ocultos? Tuve un problema similar con inotifywaitdisparar varias veces, pero me di cuenta de que era porque vim crearía un archivo .swp al editar, lo que dispararía un evento al cerrar. También recogería el evento cercano del archivo original.

Parece que estás notando el evento disparando múltiples archivos en el mismo archivo, lo cual no es algo que haya podido reproducir, esto solo sucedería una vez para el archivo temporal y una vez para el original.

Intenté una prueba rápida con nano y no creo que cree un archivo temporal (al menos para el caso de algunos caracteres), pero ¿hay algo más en su configuración que pueda depender de un comportamiento similar?

neocpp
fuente
Gracias por tus sugerencias. Me he encontrado con el problema múltiple de inotify incluso cuando creo un archivo de 1 byte muy trivial con Nano, o incluso simplemente redirigiendo un único carácter de la consola a un archivo. La "solución" que describí en mi pregunta original es mantenerme en marcha por ahora. Sin embargo, a largo plazo, la única solución que tengo es reconstruir mi servidor a partir de cero para identificar cuándo comienza el error: mi configuración con Incron, Watcher (por cierto, sucedió cuando acababa de tener Incron), MariaDB, Nginx, Redis, Memcached ... no es exactamente una "simple".
DroidOS
Por si acaso, verifique dos veces si no está monitoreando la misma carpeta dos veces. Si no, entonces, por ejemplo, cuando copio el archivo en el recurso compartido samba a través del cliente os x samba, esto sucede crear, cerrar_escribir, eliminar, crear, cerrar_escribir Cuando hago eso con un cliente de Windows, parece más razonable crear, escribir_close y nada más. Así que resuelvo mi problema monitoreando la primera modificación del archivo con este directorio IN_MODIFY, IN_ONESHOT /. sleep someTime command oneshot hace la cosa.
Edik Mkoyan