inotifywatch: продолжить просмотр после вращения файла

Я пытаюсь написать сценарий, который использует inotifywatch для просмотра изменений в файле журнала. Если конкретное сообщение записано в файл журнала, оно должно вызвать определенную функцию. Сценарий в настоящее время существует в этой базовой форме:

 while inotifywait -e modify /var/log/auth.log do alert=$(tail -n1 /var/log/auth.log | grep -E -o ".{0,7}password") if [[ $alert == "Failed password" ]] then echo "FAILURE" >> test.log elif [[ $alert == "cepted password" ]] then echo "LOGIN" >> test.log fi done 

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

Я попытался обойти это, переключившись с inotifywatch на использование tail -f но такая же проблема, похоже, применима и там.

Теперь я понимаю, что это, вероятно, можно решить, создав огромную if в которой inotifywatch не только следит за modify , но и за создание файла и перезапускает часы для модификации. Но мне нравится держать вещи простыми, так кто-нибудь знает, есть ли более простой способ? (И, пожалуйста, нет, я не хочу использовать готовые решения, такие как fail2ban и т. Д. – интересная часть для меня – это создавать подобные вещи с помощью простых инструментов.)

inotify используется для контроля файлов каталога по их inode, а не по их имени. Когда файл вращается, его содержимое больше не изменяется (за исключением короткого периода, пока демоны не будут перезагружены, так что они будут использовать только что созданный файл журнала)

AFAIK, tail -f использует систему inotify, поэтому это не поможет. Но если у вас есть рабочее решение с tail -f то используйте tail --follow=name (или tail -F ), если это поддерживается вашей версией tail (хвост POSIX этого не поддерживает). tail будет отслеживать файл, идентифицированный его именем файла. Вот выдержка из справочной страницы:

С –follow (-f) хвост по умолчанию следует за файловым дескриптором, а это означает, что даже если файл хвоста переименован, хвост продолжит отслеживать его конец. Это поведение по умолчанию нежелательно, если вы действительно хотите отслеживать фактическое имя файла, а не дескриптор файла (например, вращение журнала). В этом случае используйте –follow = name. Это заставляет хвост отслеживать названный файл таким образом, чтобы он позволял переименовывать, удалять и создавать.

[Обновить]

Пример использования:

 tail -n0 -F my_file.log \ | while read -r log_line; do do_something_with "$log_line" done 

Из-за трубы цикл while выполняется в подпроцессе, что может вызвать проблемы, если вы хотите изменить переменные за пределами цикла. Если вы используете bash , вы можете использовать этот альтернативный синтаксис, который не имеет этого нежелательного эффекта (но менее читаемый):

 while read -r log_line; do do_something_with "$log_line" done < <(tail -n0 -F my_file.log) 

Это можно сделать с помощью inotifywait с одним слоем :

 inotifywait -e move_self -e modify -m /path/to/some/file | awk '$2=="MODIFY" {system("/bin/echo Yes")}' 

Флаг -m постоянно контролирует файл, для событий move_self (который позволяет отслеживать изменение имени файла или каталога) и изменять его , передавая вывод команде awk, которая уничтожает события move_self , выполняя команду внутри системного набора круглых скобок для каждого события изменения . Вы должны будете написать свой собственный сценарий оболочки вместо моей команды echo . Обратите внимание на различные наборы апострофов и кавычек.