Почему события Inotify запускаются более одного раза

Этот вопрос возникает от другого, который я поставил на Stackoverflow. Я использую Watcher - те же проблемы применимы и к Incron - чтобы отслеживать папку и ее дочерние папки на предмет изменений и молча скрывать эти изменения в Dropbox.

Я контролирую write_close событие - IN_CLOSE_WRITE - с целью. Первоначально я смотрел modify событие, т.е. IN_MODIFY. Хотя это сработало, я обнаружил, что при записи больших файлов он будет срабатывать более одного раза. Это звучало справедливо, поэтому я перешел на IN_CLOSE_WRITE поскольку я чувствовал, что было бы справедливо предположить, что для данного файла это произойдет только один раз.

Однако это не так. Даже для очень маленького текстового файла - всего одного символа - созданного в Nano, событие происходит два раза. В лучшем случае это может привести к ненужному трафику, когда один и тот же файл синхронизируется в Dropbox два раза. В моем случае это приводит к катастрофе, так как при первом событии я выполняю синхронизацию, а затем удаляю файл на стороне сервера. Результат - во втором событии файл на стороне Dropbox становится файлом 0 байт.

Сейчас я имею дело с этим, заставляя мой сценарий синхронизации спать 10 секунд, прежде чем я сделаю что-нибудь еще, и затем проверяю, что рассматриваемый файл все еще существует до попытки синхронизации Dropbox. Это работает, потому что на второй итерации файл отсутствует, а сценарий просто завершается.

В лучшем случае это звучит хакерски. Возможно, неплохой взлом, но я бы предпочел понять - почему же даже IN_CLOSE_WRITE событие происходит более одного раза?


Некоторая дополнительная информация

  • Убедитесь, что не запущено несколько экземпляров наблюдателя.

Выход из 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

Файловая система ext4, Я должен упомянуть, что я столкнулся с точно такой же проблемой с Incron. Я запускаю демон Watcher из пакетного скрипта, выполняемого через /etc/rc2.d, Incron OTH запускается без каких-либо проблем со мной по умолчанию apt-get install incron монтаж.


Суть моей watcher.ini файл показан ниже.

[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

Я уменьшил datastore.php Скрипт к самым необходимым, чтобы убедиться, что он запускается дважды без какого-либо грязного загружаемого Dropbox + исходного кода удаления.

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

?>

Затем я создал небольшой файл по указанному пути, а затем исследовал /tmp/watcher, Проблема все еще сохраняется - файл все еще имеет две последовательные записи для $argv[1],

4 ответа

Я только что использовал IN_CLOSE_WRITE и, наконец, обнаружил проблему. Мой исходный сценарий читал почту со стандартного ввода построчно, а затем записывал каждую строку в файл. Это заставляло incron срабатывать при каждой записи строки. Я видел это по количеству событий incron и по количеству строк в файле.

Затем я изменил исходный скрипт, чтобы прочитать весь стандартный ввод перед записью файла. Как только это было установлено, я больше не видел нескольких запусков incron в одном файле.

У меня недостаточно репутации, чтобы опубликовать это как комментарий, но вы уверены, что временные, возможно скрытые файлы не создаются? У меня была похожая проблема с inotifywait запускал несколько раз, но я понял, что это потому, что vim создаст файл.swp при редактировании, который вызовет событие при закрытии. Это также подхватило бы событие закрытия из исходного файла.

Похоже, вы заметили, что событие запускает несколько файлов в одном файле, но это не то, что я смог воспроизвести - это произойдет только один раз для временного файла и один раз для оригинала.

Я попытался провести быстрый тест с nano, и я не думаю, что он вообще создает временный файл (по крайней мере, для случая с несколькими символами), но есть ли что-то еще в вашей настройке, которое могло бы полагаться на подобное поведение?

Я не уверен, но, скорее всего, первый write_close записывает в него атрибуты файла, такие как время создания, и только после этого записывает реальные данные. Фактически, rsync создает временный файл, и когда все сделано, он перемещает временный файл в реальный файл в той же папке, так что легко отслеживать, как обычно он создавался при использовании rsync, и перемещение это атомарная операция. С другой стороны, в inotify есть что-то, что можно назвать одним выстрелом, вероятно, с помощью этого мы можем инициировать что-то в первом сообщении о модификации, и, как вы предложили, поспите некоторое время перед началом операции. Я копаю это сейчас и буду обновлять, когда найду что-нибудь новое. https://superuser.com/questions/1133642/traceing-the-moment-when-file-is-completely-copied-to-samba-share-with-inotify

Я заметил, что получаю 2 события, если использую >или же cp:

      root@vm-dvde05:~# touch file
root@vm-dvde05:~# inotifywait --recursive --monitor --event modify file &
[1] 31835
root@vm-dvde05:~# Setting up watches.  Beware: since -r was given, this may take a while!
Watches established.

root@vm-dvde05:~# echo string>file
file MODIFY
file MODIFY
root@vm-dvde05:~# cat file
string
root@vm-dvde05:~# cp /etc/hosts file
file MODIFY
file MODIFY
root@vm-dvde05:~#

Но если я использую добавить >>он показывает одно событие:

      root@vm-dvde05:~# echo string2>>file
file MODIFY
root@vm-dvde05:~# kill %1
root@vm-dvde05:~#
[1]+  Terminated              inotifywait --recursive --monitor --event modify file
root@vm-dvde05:~#

Чтобы получить одно событие, которое я отслеживаю CLOSE_WRITE

Другие вопросы по тегам