2013-03-29 3 views
1

Я пишу скрипт Python, который должен содержать tail -f файл журнала.Python - Хвост logfile - sleep() против inotify?

Операционная система RHEL под управлением Linux 2.6.18.

Обычный подход, я считаю, заключается в использовании бесконечного цикла со сном, чтобы постоянно опросить файл.

Однако, поскольку мы в Linux, я думаю, что я могу использовать что-то вроде pyinotify (https://github.com/seb-m/pyinotify) или Watchdog (https://github.com/gorakhargosh/watchdog) вместо этого?

Каковы преимущества/недостатки этого?

Я слышал, что используя sleep(), вы можете пропустить события, если файл быстро растет - это возможно? Я думал, что хвост GNU также использует сон?

Приветствие, Виктор

+0

GNU tail implementation - http://git.savannah.gnu.org/cgit/coreutils.git/tree/src/tail.c Поиск «inotify», они, похоже, используют его, если он доступен. – Dogbert

+0

Обратите внимание на третий возможный ответ: 'popen = subprocess.Popen ([" tail "," -f ", filename])'. Затем используйте обычные методы чтения каналов на popen.stdout, для которых у вас, вероятно, уже есть поддержка, в вашей структуре. –

ответ

5

Чистейшее решение будет Inotify во многих отношениях - это более или менее точно, что он предназначен для, в конце концов. Если файл журнала менялся очень быстро, вы могли бы потенциально рискнуть разбудить почти постоянно, что не обязательно было бы особенно эффективным, однако вы всегда могли бы смягчить это, добавив небольшую задержку после того, как inotify filehandle вернет событие , На практике я сомневаюсь, что это будет проблемой для большинства систем, но я подумал, что стоит упомянуть, если ваша система очень жестко связана с ресурсами процессора.

Я не вижу, как подход sleep() будет пропускать обновления файлов, за исключением случаев, когда файл усечен или повернут (т. Е. Переименован и создается другой файл с тем же именем). Это сложный случай, чтобы справиться с тем, что вы делаете, и вы можете использовать трюки, например, периодически открывать файл по имени, чтобы проверить его вращение. Прочтите справочную страницу tail, потому что она обрабатывает многие такие случаи, и они будут довольно распространены для файлов журналов, в частности (поворот журнала широко считается хорошей практикой).

Недостатком sleep() является, конечно же, то, что вы закончите дорабатывать свои чтения с задержками между ними, а также что у вас есть накладные расходы на постоянное пробуждение и опрос файла, даже если он не меняется. Однако, если вы сделали это, скажем, один раз в секунду, накладные расходы, вероятно, не заметны в большинстве систем.

Я бы сказал, что inotify - лучший выбор, если вы не хотите оставаться совместимым, и в этом случае простой резерв с использованием sleep() по-прежнему вполне резонный.

EDIT:

Я просто понял, что я забыл упомянуть - простой способ для проверки файла переименуемого выполнить os.fstat(fd.fileno()) на вашем открытом дескрипторе и os.stat() на имени файла, вы открыли и сравнить Результаты. Если os.stat() не работает, тогда ошибка сообщит вам, был ли файл удален, а если нет, то сравнение полей st_ino (номер индекса) сообщает вам, был ли файл удален, а затем заменен на новое одноименное имя.

Обнаружение усечения сложнее - эффективно ваш указатель чтения остается с тем же смещением в файле, и чтение ничего не возвращает, пока размер содержимого файла не вернется туда, где вы были - тогда файл будет считаться с этой точки как обычно.Если вы часто вызываете os.stat(), вы можете проверить размер файла, идущего в обратном направлении - в качестве альтернативы вы можете использовать fd.tell() для записи вашей текущей позиции в файле, а затем выполнить явный поиск в конце файла и снова вызвать fd.tell(). Если значение меньше, то файл будет усечен под вами. Это безопасная операция, пока вы сохраняете исходную позицию файла, потому что вы всегда можете вернуться к ней после проверки.

В противном случае, если вы используете inotify в любом случае, вы можете просто посмотреть родительский каталог для изменений.

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