Por que eventos inotify disparam mais de uma vez

13

Essa pergunta surge de outra que eu havia colocado no Stackoverflow . Estou usando o Watcher - os mesmos problemas se aplicam ao Incron - para monitorar uma pasta e suas pastas filho em busca de alterações e, silenciosamente, esquecer essas alterações no Dropbox.

Monitoro o write_closeevento - IN_CLOSE_WRITE- para o efeito. Originalmente, eu estava assistindo o modifyevento, ou seja, IN_MODIFY. Enquanto isso funcionava, descobri que ao escrever arquivos grandes, ele disparava mais de uma vez. Parecia justo, então mudei para, IN_CLOSE_WRITEpois achava razoavelmente justo supor que, para um determinado arquivo, isso ocorreria apenas uma vez.

No entanto, esse não é o caso. Mesmo para um arquivo de texto muito pequeno - apenas um caractere - criado no Nano, o evento ocorre duas vezes. Na melhor das hipóteses, isso pode resultar em tráfego desnecessário quando o mesmo arquivo é sincronizado no Dropbox duas vezes. No meu caso, isso leva a um desastre, já que no primeiro evento eu executo a sincronização e excluo o arquivo do lado do servidor. O resultado - no segundo evento, o arquivo do lado do Dropbox se torna um arquivo de 0 byte.

Por enquanto, estou lidando com isso, deixando meu script de sincronização por 10s antes de fazer qualquer outra coisa e depois verifico se o arquivo em questão ainda existe antes de tentar a sincronização do Dropbox. Isso funciona porque na segunda iteração o arquivo está ausente e o script é finalizado.

Isso parece insensato, no melhor dos casos. Talvez não seja um truque ruim, mas eu prefiro entender - apenas por que o IN_CLOSE_WRITEevento ocorre mais de uma vez?


Algumas informações adicionais

  • Verifique para garantir que não haja várias instâncias do observador em execução.

Saída 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

O sistema de arquivos é ext4. Devo mencionar que encontrei exatamente o mesmo problema com o Incron. Inicio o daemon Watcher a partir de um script em lote executado via /etc/rc2.d. O Incron OTH é iniciado sem nenhuma confusão por mim através de sua apt-get install incroninstalação padrão .


A essência do meu watcher.iniarquivo é mostrada abaixo.

[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

Reduzi o datastore.phpscript ao essencial para verificar se ele foi acionado duas vezes sem nenhum dos meus bagunçados códigos do Dropbox upload + source delete.

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

?>

Criei um pequeno arquivo no caminho em questão e depois examinei /tmp/watcher. O problema ainda persiste - o arquivo ainda possui duas entradas sucessivas para $argv[1].

DroidOS
fonte
1
Tentei muitas variações, mas não consigo duplicar seu problema com várias demissões de IN_CLOSE_WRITE. Tudo o que fiz causou uma única saída inotify. Eu vou continuar tentando as coisas. Mas até agora, apenas perguntas. Qual sistema de arquivos? Ext4? De outros?
Lornix
@ lornix - veja as edições da minha pergunta. O sistema de arquivos está ext4e tenho certeza de que não tenho duas instâncias do Watcher em execução. Corri para o mesmo problema com o Incron.
DroidOS
Você disse 'Eu executo a sincronização e excluo o arquivo do servidor'. Essa exclusão aciona o segundo evento? Você pode desativar a deleterotina e tentar novamente?
Germar
@ Germar - veja a edição da minha pergunta. Mesmo com o script de sincronização sem sincronização real e sem unlinkpersistir o problema #
DroidOS
Desculpe, sem ideias, não consigo reproduzir o problema em nenhuma das minhas máquinas. Eu recebo um evento, não mais. Algo mais está envolvido, algo não mencionado. Você tem antivírus instalado? algo assim?
Lornix

Respostas:

1

Não tenho certeza, mas provavelmente o primeiro write_close grava atributos de arquivo nele, como o tempo de criação, e somente depois disso grava dados reais. De fato, o rsync cria um arquivo temporário e, quando tudo é feito, move o arquivo temporário para o arquivo real na mesma pasta, para que seja fácil monitorar o processo normalmente criado quando você usa o rsync, e move é uma operação atômica. Por outro lado, há algo que apenas uma tentativa de inotify, provavelmente, usando isso, podemos disparar algo na primeira mensagem de modificação e, como você sugeriu dormir por um período razoável antes de iniciar a operação. Estou cavando isso agora e será atualizado quando encontrar algo novo. /superuser/1133642/traceing-the-moment-when-file-is-completely-copied-to-samba-share-with-inotify

Edik Mkoyan
fonte
Você pode muito bem ter apontado algo bastante válido aqui. Isso exigirá alguma investigação. Obrigado pela dica. Vou postar de volta caso ache que isso seja um problema.
DroidOS
Eu não acho que o ATTRIB adiciona algo ao arquivo em si, eu estava errado.
Edik Mkoyan
0

Não tenho representante suficiente para postar isso como um comentário, mas você tem certeza de que arquivos temporários, possivelmente ocultos, não estão sendo criados? Eu tive um problema semelhante ao inotifywaitdisparar várias vezes, mas percebi que era porque o vim criaria um arquivo .swp ao editar, o que dispararia um evento ao fechar. Ele também pegaria o evento close do arquivo original.

Parece que você está percebendo o evento disparando vários arquivos no mesmo arquivo, o que não é algo que eu possa reproduzir - isso aconteceria apenas uma vez no arquivo temporário e no original.

Eu tentei um teste rápido com o nano e não acho que ele crie um arquivo temporário (pelo menos para os poucos caracteres), mas há mais alguma coisa na sua configuração que possa depender de um comportamento semelhante?

neocpp
fonte
Obrigado por suas sugestões. Corri para o inotify multiple issue, mesmo quando crio um arquivo de 1 byte muito trivial com o Nano - ou mesmo redirecionando um único caractere do console para um arquivo. A "solução" que descrevi na minha pergunta original está me mantendo por agora. No entanto, a longo prazo, a única solução que tenho para reconstruir meu servidor a partir do zero para identificar exatamente quando o erro começa - minha configuração com o Incron, Watcher (por exemplo, quando eu tinha acabado de usar o Incron), MariaDB, Nginx, Redis, Memcached ... não é exatamente "simples".
DroidOS
Por precaução, verifique se não está monitorando a mesma pasta duas vezes. Caso contrário, por exemplo, quando copio o arquivo para o compartilhamento samba via cliente os x samba, isso acontece criar, fechar_escrever, excluir, criar, fechar_escrever Quando faço isso com um cliente Windows, parece mais razoável criar, escrever_close e nada mais. Portanto, resolvo meu problema monitorando a primeira modificação do arquivo com este diretório IN_MODIFY, IN_ONESHOT /. sleep someTime comanda oneshot faz a coisa.
Edik Mkoyan