- Подписка на печатную версию:
- Подписка на электронную версию:
- Подшивки старых номеров журнала (печатные версии)
LXF139:Inotify
Материал из Linuxformat.
- Inotify Этот удобный модуль ядра следит за вашей файловой системой, как ястреб
Содержание |
Inotify: Следим за системой
- Коэн Вервлоесем любит контролировать события в своей файловой системе. Благодаря Inotify он не упускает ни единого изменения файлов.
Есть немало случаев, когда вам нужно бы знать, что творится в неком каталоге. Нужда – мать изобретений, и последние версии дистрибутивов Linux изобрели для этой цели множество инструментов. Например, если вы откроете свой каталог Pictures в Dolphin при импорте фотографий с цифровой камеры в Digikam, новые файлы тут же отобразятся в окне Dolphin. Утилиты рабочего стола для поиска используют данную функцию для переиндексирования измененных файлов – чтобы ежеминутно не сканировать изменения файловой системы. А если такая функция требуется, скажем, в ваших скриптах оболочки? Благодаря модулю ядра Linux по имени Inotify получить ее не слишком сложно, что мы и докажем на данном уроке. Мы рассмотрим работу Inotify и его возможности, а также способ легко добавить его на панель инструментов.
Под капотом
Inotify – компонент, обеспечивающий мониторинг различных изменений файлов в файловых системах; он входит в ядро Linux, начиная с версии 2.6.13. Inotify позволяет следить за одним или несколькими файлами или каталогами на предмет событий из указанного набора: открытие файла или папки; чте-ние, модификация или изменение атрибутов (например, метки или разрешения) открытого файла; закрытие, перемещение, создание или удаление файла. В таблице ниже все эти события перечислены.
Вы можете использовать Inotify для целого ряда задач: выявить изменения в файлах и каталогах (например, в файле настройки или почтовом каталоге), автоматически восстановить удаленные критически важные файлы настройки, отправить вам по почте сообщение, когда файл загружается в конкретных каталогах на web-сервере, и так далее. Без Inotify ваша программа или скрипт должны будут проверять файлы периодически (такой образ действий называется «опрос» [polling]) – это очень медленно и тормозит работу всей системы. С Inotify ядро уведомляет программу по каждому указанному событию. Inotify даже может смотреть файлы на съемных носителях, не мешая вам размонтировать диск.
Отметим, что в ядре Linux 2.6.31, Inotify сменился на Fsnotify, но поверх Fsnotify реализован привычный интерфейс Inotify. Так что на практике большой разницы нет: инструменты, которые мы используем на нашем уроке, без проблем работают на всех ядрах, начиная с 2.6.13. Если вы строите собственное ядро, обеспечьте его компиляцию с поддержкой Inotify (CONFIG_Inotify и CONFIG_INOTIFY_USER). Все основные дистрибутивы Linux поддерживают Inotify из коробки с ядром по умолчанию. Если вы не уверены, есть ли Inotify в вашем, проверьте это следующей командой, которая должна выдать показанный здесь же результат:
$ grep INOTIFY /boot/config-$(uname -r) CONFIG_INOTIFY=y CONFIG_INOTIFY_USER=y
Следите за событиями
Вы хотите быть в курсе, когда происходит определенное событие? Используйте команды espeak, emacspeak или festival с iwatch или inoticoming.
Поскольку Inotify находится в ядре, все программы Linux могут пользоваться его возможностями без специальных библиотек. Разработчик просто должен употреблять правильные системные вызовы. Но, понятно, вам как конечному пользователю вряд ли захочется писать программу на С, чтобы посмотреть события в файловой системе. Поэтому быстренько был сформирован набор из двух простых, но мощных инструментов командной строки: Inotify-tools. Большинство дистрибутивов предлагают этот проект в форме пакета с тем же названием; или можно скачать его с сайта http://github.com/rvoicilas/inotify-tools.
Инструменты из пакета Inotify-tools – inotifywait и inotifywatch. Начнем со второго: он дает представление, какую информацию можно получить с Inotify. Просто введите команду
$ inotifywatch -r ~
Он будет рекурсивно собирать информацию по всем событиям файловой системы в вашем домашнем каталоге.
Пока эта команда работает, запустите какую-нибудь программу – хотя бы Firefox – а затем прервите работу inotifywatch с помощью Ctrl+C. Тут выдастся таблица с подсчетом всех событий, касающихся файлов и каталогов в вашем домашнем каталоге. Это простой способ увидеть, к каким файлам обращается Firefox и часто ли это бывает.
Есть и способ более тонкий: применить опцию -е для сбора информации по конкретным событиям. Вот как получить уведомление о создании или удалении файла в вашем домашнем каталоге:
$ inotifywatch -e create,delete -r ~
По умолчанию строки в таблице отсортированы по убыванию значения столбца total, что дает представление о наиболее активных файлах. Однако с помощью -d <event> можно отсортировать строки по убыванию значений для заданного события, а -a <event> делает то же самое, но по возрастанию. Сортировка применима ко всем событиям, кроме перемещения и закрытия (которые делятся на moved_to и moved_from и close_write и close_nowrite).
Вот вам еще полезные опции: --exclude <pattern> и --excludei <pattern> велят inotifywatch не обрабатывать события, чьи названия соответствуют заданному регулярному выражению, с учетом регистра (--exclude) – или нечувствительно к регистру (--excludei). -t <seconds> велит inotifywatch потрудиться в течение указанного периода времени, затем вывести по нему статистикуи завершить работу.
Это особенно интересно для неинтерактивного использования inotifywatch – например, в сравнительном тесте.
В режиме реального времени
Inotifywatch – неплохой инструмент для любителей статистики; ну, а если вы хотите узнавать о событии в сей же момент, когда оно происходит? На это в Inotify-tools имеется другая программа, inotifywait. Пусть вы хотите рекурсивно контролировать все события файловой системы в вашей домашней директории. Введите команду
$ inotifywait -mr ~
После этого запустите Firefox, посетите пару сайтов... и вы удивитесь количеству файлов, которые читал ваш web-браузер.
Благодаря опции -m (мониторинг), вы сразу же получите извещение о любом изменении в вашем домашнем каталоге. Каждая строка на выходе указывает каталог, события и (если надо) файл. Вы также можете проверить это, создав, а затем удалив каталоги и файлы, например:
$ mkdir ~/testinotify $ echo TEST > ~/testinotify/test.txt $ touch ~/testinotify/test.txt $ rm ~/testinotify/test.txt $ rmdir ~/testinotify
Ниже приводится результат работы inotifywait после ввода этих команд:
$ inotifywait -mr ~ Установка наблюдения. Учтите: из-за параметра -r это потребует времени! Наблюдение установлено. /home/koan/ CREATE,ISDIR testinotify /home/koan/ OPEN,ISDIR testinotify /home/koan/ CLOSE_NOWRITE,CLOSE,ISDIR testinotify /home/koan/testinotify/ CREATE test.txt /home/koan/testinotify/ OPEN test.txt /home/koan/testinotify/ MODIFY test.txt /home/koan/testinotify/ CLOSE_WRITE,CLOSE test.txt /home/koan/testinotify/ OPEN test.txt /home/koan/testinotify/ ATTRIB test.txt /home/koan/testinotify/ CLOSE_WRITE,CLOSE test.txt /home/koan/testinotify/ DELETE test.txt /home/koan/ DELETE,ISDIR testinotify /home/koan/testinotify/ DELETE_SELF
Попробуйте ввести эти команды в одном окне терминала, глядя на результат inotifywait в другом окне терминала рядом с первым: это весьма поучительно!
За событиями можно наблюдать и в ваших программах: привязки Inotify предусмотрены для самых популярных программ и языков программирования, в том числе Perl, Python и Ruby.
Как и с inotifywatch, можно использовать опцию -e, чтобы получить результат только по конкретным событиям, опцию -t для задания периода работы в секундах, и --exclude или --excludei, чтобы исключить часть файлов.
Так, все отлично, но почему эта команда называется inotifywait? Wait [ждать] в названии вроде не имеет смысла? На самом деле – по умолчанию (а не так, как мы применяли команду до сих пор, если только вы не указывали опцию -m), inotifywait действительно ждет указанного события в файловой системе и завершает работу при первом появлении события. Это полезно, когда нужно, чтобы ваш скрипт ожидал создания некого файла, а затем что-нибудь делал.
Теперь вам, вероятно, захотелось использовать inotifywait в собственных скриптах оболочки. Но прежде чем начать писать пространный скрипт, который использует inotifywait, автоматически преобразует любой файл, поступающий в папку Pictures, в миниатюру и кидает ее на web-сервер, давайте на шаг отступим. Разве некому было насоздавать на основе Inotify скриптов для базовых задач? Правильно: изобретать велосипед незачем. Поэтому не будем на нашем уроке лепить свои скрипты, но укажем на существующие инструменты для конкретных случаев. Конечно, если ни один из них вам не подходит, или у вас аллергия на Придумано_Не_Мной, почему бы и не написать скрипты самому.
Мгновенное извещение
Одна из программ, построенных на Inotify – iwatch (http://iwatch.sourceforge.net); она может сделать запись в системный журнал, выполнить команду или отправить вам электронное письмо, как только произойдет заданное событие файловой системы. Это идеальный инструмент для системного администратора, которому требуется простой способ немедленного уведомления при подозрительных событиях в файловой системе. Так, например, легко следить рекурсивно за изменениями в /etc:
$iwatch -r /etc
В отличие от предыдущих инструментов Inotify, по умолчанию iwatch следит только за событиями close_write, create, delete, move, delete_self и move_self, что и логично с точки зрения назначения программы: блюсти целостность вашей системы. При желании указать другой набор событий для наблюдения воспользуйтесь опцией -е.
Исключения можно определить с помощью -х для полного пути или с -X для регулярных выражений. А можно и по-другому: если вы хотите оповещения только для отдельных файлов или каталогов, используйте опцию -t с регулярным выражением для фильтрации контролируемых файлов. Ниже – пример предупреждения об изменениях в /etc/passwd и /etc/shadow (где мы опустили -r, потому что /etc нам не надо контролировать рекурсивно):
$ iwatch -t “passwd|shadow” /etc
До сих пор не просматривалось ничего такого, чего нельзя сделать в inotifywait. Но две уникальные опции у iwatch прибавлены: -m для отправки уведомления по электронной почте и -с для выполнения команды.
Первый из этих аргументов прост. Если вы хотите получать уведомления по электронной почте, когда кто-то покушается на файл в /etc, выполните следующее:
$ iwatch -m your@emailaddress.com -r /etc
Конечно, это сработает, только если машина, где вы ее выполняете, имеет почтовый сервер, настроенный для отправки почты на внешние хосты. В противном случае сгодится и локальный почтовый ящик, например, user@host, хотя это вариант, очевидно, менее безопасен, если вы используете iwatch для проверки, не влез ли кто-то в компьютер.
-с – тоже интересная опция. Она указывает команду, выполняемую в случае указанного события; можно также использовать переменные типа %f для полного пути к файлу, вызывавшему событие, %р для названия программы (iWatch) и %v для вывода версии iwatch. Вот пример:
$ iwatch -t “passwd|shadow” -c “logger -t ‘%p %v’ %f has been changed “ /etc
При этом используется команда logger, регистрирующая предупреждения в журнале, когда кто-то модифицирует /etc/passwd или /etc/shadow. Включите свое воображение и подумайте, какие еще команды вызывать в ответ на определенные события файловой системы.
Другая интересная особенность iwatch – режим демона: при этом (с опцией -d) iwatch выполняется как фоновая и берет конфигурацию из /etc/iwatch/iwatch.xml (или из альтернативного файла конфигурации, если указать опцию -f). В этом XML-файле укажите список папок и файлов для мониторинга и адреса электронной почты для уведомлений и/или команды для выполнения. Это полезно, если у вас есть сложный алгоритм для проверки: например, вы хотите, чтобы изменения в /var/www передавались web-мастеру, а изменения в /etc – системному администратору. Сайт Iwatch – поучительный пример файла XML, где iwatch используется в режиме демона.
Inoticoming
Еще один инструмент – специально для мониторинга появлений файлов в указанном каталоге – inoticoming. Он пригодится, например, чтобы отслеживать прибытие файлов на FTP-сервер и обрабатывать их по завершении загрузки. Или можно автоматически преобразовывать все JPG-файлы, загружаемые в каталог с изображениями web-сервера, в миниатюры. Команда для этих задач:
$ inoticoming --initialsearch /var/www/images --suffix .jpg --chdir /var/www/images convert -resize 200 {} thumbnails/{} \;
Конечно, следует позаботиться о должном разрешении на запись в каталоге /var/www/images/thumbnails для процесса inoticoming. С помощью глобальной опции --initialsearch мы также велим inoticoming обрабатывать все файлы в этом каталоге, но вы можете ее опустить, если вам этого не требуется. Затем мы определяем папку /var/www/images, где работать (отметим, что inoticoming не будет смотреть подкаталоги этого каталога), и назначаем действия: брать только файлы с расширением .jpg и перед выполнением команды перейти в папку /var/www/images. В конце строки определена команда для выполнения над каждым входящим файлом – это инструмент convert из пакета ImageMagick.
Inoticoming меняет переменные в скобках {} на имя обрабатываемого файла (только имя файла, без пути), и команда должна закончиться точкой с запятой, в оболочке экранируемой символом \.
В случае такого запуска inoticoming работает как демон, в фоновом режиме. Глобальная опция --foreground указывает оставаться на переднем плане. В man-странице перечислены прочие опции, например --prefix и --regexp. Inoticoming менее гибок, чем inotifywait, но для обработки входящих файлов в одном каталоге без подкаталогов это удобный инструмент.
Другие инструменты
Инструменты на базе функций Inotify перечисленными не исчерпываются. Например, есть incron, Cron-подобный демон, выполняющий действия не на конкретную дату или время, а по информации Inotify об определенном событии. Есть также два инструмента для синхронизации каталогов с помощью Inotify: inosync и lsyncd. Вместо использования rsync в crontab для периодической синхронизации двух каталогов каждые Х минут или часов, эти инструменты делают синхронизацию немедленно (и, благодаря Inotify, без опроса). Если вы решили создать самопальный Dropbox, один из этих инструментов вам поможет.
Под FreeBSD, OpenBSD, NetBSD и Mac OS X нет Inotify, но есть схожий интерфейс оповещения о событиях, Kqueue.
Но лучший признак популярности Inotify – то, что GNU tail (часть GNU coreutils) поддерживает Inotify начиная с версии 7.5 (с августа 2009 года) при использовании опции -f. До этого вам приходилось использовать отдельный инструмент, называемый inotail. Выходит, не исключено, что вы уже какое-то время пользовались Inotify, не подозревая о том.
Доступные события Inotify
- access Открыт наблюдаемый файл или файл в наблюдаемом каталоге.
- modify Изменен наблюдаемый файл или файл в наблюдаемом каталоге.
- attrib Изменены метаданные наблюдаемого файла или файла в наблюдаемом каталоге. (включая метки, права доступа, расширенные атрибуты и т. д.).
- close_write Закрыт наблюдаемый файл или файл в наблюдаемом каталоге, открывавшийся в режиме записи.
- close_nowrite Закрыт наблюдаемый файл или файл в пределах наблюдаемого каталога, открывавшийся только для чтения.
- close Закрыт наблюдаемый файл или файл в наблюдаемом каталоге. Заметьте, что слежение здесь реализовано за событиями close_write или close_nowrite, поэтому на выходе вы увидите не событие close, а одно из этих двух.
- open Открыт наблюдаемый файл или файл в наблюдаемом каталоге.
- moved_to Файл или каталог перемещен в наблюдаемый каталог. Событие происходит, даже если файл перемещается просто внутри каталога (т. е. переименован).
- moved_from Файл или каталог перемещен из наблюдаемого каталога. Событие происходит, даже если файл перемещается просто внутри каталога (т. е. переименован).
- moved Файл или каталог перемещен из наблюдаемого каталога или в него. Заметьте, что это реализовано с помощью moved_to и moved_from, поэтому на выходе вы увидите не событие move, а одно из этих двух.
- create Создан файл или каталог в наблюдаемом каталоге.
- delete Удален файл или каталог в наблюдаемом каталоге.
- delete_self Файл или каталог удален. После этого наблюдение с файла или каталог снимается. Заметьте, что событие может произойти, даже если он явно не наблюдался.
- unmount Отмонтирована файловая система, где находился наблюдаемый файл или каталог. После этого наблюдение с файла или каталог снимается. Заметьте, что событие может произойти, даже если он явно не наблюдался.
Просвети меня!
Если вы используете inotifywatch, inotifywait или другой инструмент Inotify на большом дереве каталогов, например /, вы скоро превысите стандартный лимит на число просмотров Inotify, потому что Inotify должен создать один просмотр на подкаталог. К счастью, эти инструменты выдают подробное сообщение об ошибке, и они скажут вам, что делать: увеличьте отведенное на пользователя число просмотров Inotify, которое находится в файле /proc/sys/fs/inotify/max_user_watches. Взгляните на значение по умолчанию этого параметра ядра и повысьте его, если требуется:
# cat /proc/sys/fs/inotify/max_user_watches 8192 # echo 32768 > /proc/sys/fs/inotify/max_user_watches # cat /proc/sys/fs/inotify/max_user_watches 32768
Теперь наблюдайте себе хоть за всей файловой системой. Однако эта настройка не переживет перезагрузки дистрибутива Linux. При желании сделать данный параметр ядра постоянным, добавьте в /etc/sysctl.conf такую строку:
fs.inotify.max_user_watches = 32768
Или, если в вашем дистрибутиве нет /etc/sysctl.conf, добавьте следующую строку в /etc/rc.local, до строки, содержащей exit 0:
echo 32768 > /proc/sys/fs/inotify/max_user_watches