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

13

Этот вопрос возникает из другого, который я поставил на 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].

DroidOS
источник
1
Я перепробовал много вариантов, но не могу продублировать вашу проблему с несколькими срабатываниями IN_CLOSE_WRITE. Все, что я сделал, вызывает один вывод inotify. Я собираюсь продолжать пробовать вещи. Но пока только вопросы. Какая файловая система? Ext4? Другой?
Lornix
@ lornix - пожалуйста, смотрите изменения к моему вопросу. Файловая система есть, ext4и я уверен, что у меня не работает два экземпляра Watcher. Я столкнулся с той же проблемой с Incron.
DroidOS
Вы сказали: «Я выполняю синхронизацию, а затем удаляю файл на стороне сервера». Это удаление вызывает второе событие? Вы можете отключить deleteрутину и попробовать еще раз?
Джермар
@Germar - см. Редактирование на мой вопрос. Даже если сценарий синхронизации не выполняет никакой реальной синхронизации и unlinkпроблема не
устранена
Извините, скорее из-за идей, я не могу воспроизвести проблему ни на одной из моих машин. Я получаю одно событие, не больше. Что-то еще вовлечено, что-то не упомянуто. У вас установлен антивирус? что-нибудь подобное?
Lornix

Ответы:

1

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

Эдик Мкоян
источник
Вы, возможно, хорошо положили палец на что-то вполне обоснованное здесь. Это потребует некоторого расследования. Спасибо за чаевые. Я отправлю обратно в случае, если я обнаружу, что это как-то проблема.
DroidOS
Я не думаю, что ATTRIB что-то добавляет в сам файл, я ошибся.
Эдик Мкоян
0

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

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

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

neocpp
источник
Спасибо вам за ваши предложения. Я столкнулся с множественной проблемой inotify, даже когда я создаю очень простой 1-байтовый файл с Nano, или даже просто перенаправляя один символ из консоли в файл. «Решение», которое я обрисовал в своем первоначальном вопросе, пока не дает мне покоя. Тем не менее, в долгосрочной перспективе единственное решение, которое мне нужно, это перестроить свой сервер, начиная с нуля, чтобы определить, когда именно начинается ошибка - мои настройки с Incron, Watcher (кстати, это произошло, когда у меня был только Incron), MariaDB, Nginx, Redis, Memcached ... не совсем "простой".
DroidOS
На всякий случай дважды проверьте, не отслеживаете ли вы одну и ту же папку дважды. Если нет, то, например, когда я копирую файл в общий ресурс samba с помощью клиента os x samba, это происходит create, close_write, delete, create, close_write. Когда я делаю это с Windows-клиентом, это выглядит более разумным, create, write_close и ничего более. Поэтому я решаю свою проблему, отслеживая первую модификацию файла с этим каталогом IN_MODIFY, IN_ONESHOT /. Команды сна someTimeShotShot делает вещь.
Эдик Мкоян