- Подписка на печатную версию:
- Подписка на электронную версию:
- Подшивки старых номеров журнала (печатные версии)
LXF121:Inotify
Материал из Linuxformat.
- Inotify Отслеживаем изменения в файловой системе Linux-компьютера
Содержание |
Inotify: Действия по событиям
- Создание, изменение и удаление файлов и каталогов – это вещи, происходящие в вашей системе по тысяче раз на дню. Их можно отследить и применить для вашего удобства, утверждает Николай Кузнецов.
Для начала – немного теории. Inotify – это подсистема ядра Linux, позволяющая отслеживать события в файловой системе. Причем происходит это в так называемом «реактивном режиме» (то есть по событию), в отличие от режима «активного» – постоянного сканирования изменений. Это предоставляет нам достаточно эффективный механизм для самых различных нужд. И хоть появилась эта функция сравнительно недавно (начиная с ядра версии 2.6.13‑rc3), ее рождение повлекло за собой значительные и не очень улучшения в различных программах, таких как: Beagle (система индексации и быстрого поиска файлов на рабочем столе), auditd (служба аудита), Brasero (программа записи CD/DVD в GNOME), tailf (эффективный аналог команды tail -f), udevd (подсистема работы с устройствами) и многие другие. Мы же продемонстрируем возможности Inotify на примере двух утилит: iwatch и incron. На данном уроке будет использоваться SUSE 11, но все действия будут аналогичными и в других дистрибутивах. Если же вы предпочтете SUSE, то сможете найти все указанные пакеты при помощи поиска на сайте http://software.opensuse.org/search.
iПосмотрим: iwatch
С помощью iwatch можно легко наблюдать, какие изменения происходят в определенной части дерева каталогов файловой системы. Для примера, запустим следующую команду:
# iwatch -v -r /etc/
Она будет подробно (-v) сообщать обо всем, что происходит в директории /etc и во всех ее поддиректориях (-r). Теперь можно открыть вашу любимую графическую программу для настройки чего-нибудь (в SUSE попробуйте YaST, в Fedora – утилиты system-config-...) и посмотреть, какие изменения она вносит в общесистемные конфигурационные файлы.
Давайте переключимся на другой терминал и выполним:
# touch /etc/issue
В результате на консоли с iwatch можно будет увидеть следующее:
[15/Jun/2009 14:08:02] IN_CLOSE_WRITE /etc/issue [15/Jun/2009 14:08:02] * /etc/issue is closed
Рассмотрим более сложный пример: разберемся, что происходит при создании нового пользователя командой
# useradd testuser
Вывод iwatch здесь будет куда более многословным:
[15/Jun/2009 14:10:06] IN_CREATE /etc/passwd.tmpZRwKCR [15/Jun/2009 14:10:06] IN_CLOSE_WRITE /etc/passwd.tmpZRwKCR [15/Jun/2009 14:10:06] IN_DELETE /etc/passwd.old [15/Jun/2009 14:10:06] * /etc/passwd.old is deleted [15/Jun/2009 14:10:06] IN_CREATE /etc/passwd.old [15/Jun/2009 14:10:06] IN_MOVED_FROM /etc/passwd.tmpZRwKCR [15/Jun/2009 14:10:06] IN_MOVED_TO /etc/passwd [15/Jun/2009 14:10:06] * /etc/passwd.tmpZRwKCR is moved to /etc/passwd [15/Jun/2009 14:10:06] IN_CREATE /etc/shadow.tmpCsjybQ [15/Jun/2009 14:10:06] IN_CLOSE_WRITE /etc/shadow.tmpCsjybQ [15/Jun/2009 14:10:06] IN_DELETE /etc/shadow.old [15/Jun/2009 14:10:06] * /etc/shadow.old is deleted [15/Jun/2009 14:10:06] IN_CREATE /etc/shadow.old [15/Jun/2009 14:10:06] IN_MOVED_FROM /etc/shadow.tmpCsjybQ [15/Jun/2009 14:10:06] IN_MOVED_TO /etc/shadow [15/Jun/2009 14:10:06] * /etc/shadow.tmpCsjybQ is moved to /etc/shadow [15/Jun/2009 14:10:06] IN_CREATE /etc/group.tmpfr7KLO [15/Jun/2009 14:10:06] IN_CLOSE_WRITE /etc/group.tmpfr7KLO [15/Jun/2009 14:10:06] IN_DELETE /etc/group.old [15/Jun/2009 14:10:06] * /etc/group.old is deleted [15/Jun/2009 14:10:06] IN_CREATE /etc/group.old [15/Jun/2009 14:10:06] IN_MOVED_FROM /etc/group.tmpfr7KLO [15/Jun/2009 14:10:06] IN_MOVED_TO /etc/group [15/Jun/2009 14:10:06] * /etc/group.tmpfr7KLO is moved to /etc/group [15/Jun/2009 14:10:06] IN_CREATE /etc/group.tmpwsLtmN [15/Jun/2009 14:10:06] IN_CLOSE_WRITE /etc/group.tmpwsLtmN [15/Jun/2009 14:10:06] IN_DELETE /etc/group.old [15/Jun/2009 14:10:06] * /etc/group.old is deleted [15/Jun/2009 14:10:06] IN_CREATE /etc/group.old [15/Jun/2009 14:10:06] IN_MOVED_FROM /etc/group.tmpwsLtmN [15/Jun/2009 14:10:06] IN_MOVED_TO /etc/group [15/Jun/2009 14:10:06] * /etc/group.tmpwsLtmN is moved to /etc/group [15/Jun/2009 14:10:06] IN_CLOSE_WRITE /etc/.pwd.lock [15/Jun/2009 14:10:06] * /etc/.pwd.lock is closed
В листинге видны следующие inotify-события:
- IN_CREATE – был создан файл или директория;
- IN_MOVED_FROM\IN_MOVED_TO – файл перемещался (откуда и куда),
- IN_DELETE – файл был удален,
- IN_CLOSE_WRITE – файл был закрыт после открытия в режиме для записи.
Из вывода iwatch становится ясно, какие файлы создавались/перемещались/удалялись во время выполнения команды useradd. В целом, картина известная: изменяются файлы /etc/passwd, /etc/shadow и /etc/group, а их старые копии сохраняются в /etc/passwd.old, /etc/shadow.old и /etc/group.old, соответственно. А вот про существование файла /etc/.pwd.lock я, например, не знал.
Кстати, обратите внимание, как происходит изменение файлов. Содержимое не перезаписывается: вместо этого создается новый временный файл, в который вносятся все необходимые строки, после чего он переименовывается. Помните споры вокруг проблем с отложенной записью в ext4? Отрадно понимать, что useradd (как, впрочем, и все грамотно написанные приложения Unix) этой проблеме не подвержен.
Получив представление о событиях Inotify, приступим к настройке службы incron.
inПопланируем: incron
Что же такое incron? Это – вариация службы Сron, выполняющая задания по событиям Inotify, а не по таймеру. Давайте реализуем при его помощи автоматическую сортировку по типам для файлов, сбрасываемых на рабочий стол пользователя testuser: музыка – в один каталог, фотоснимки – в другой, и так далее.
Для этого создаем правило incron, запустив следующую команду:
# incrontab -e
и набрав такую строку:
/home/testuser/Desktop IN_CREATE /usr/local/bin/Download_Sort.sh $#
Таким образом, мы будем отслеживать событие In_CREATE (появление нового файла или директории) в каталоге /home/testuser/Desktop, и в случае, если оно произойдет, запускать скрипт /usr/local/bin/Download_Sort.sh, передавая ему в качестве аргумента имя созданного файла (оно, согласно документации incron, хранится в переменной $#).
Далее, создаем сам сценарий /usr/local/bin/Download_Sort.sh:
Вместо редактора по умолчанию (Vim) правила incron можно вводить при помощи любого другого, предварительно выполнив команду вроде export EDITOR=gedit или export EDITOR=mcedit, то есть установив переменную окружения $EDITOR.
#!/bin/bash DIR=/home/testuser/Desktop { echo “File: $i” case “$1” in *.avi|*.flv|*.vob) mv -v “$DIR/$1” $DIR/Downloads/_Video ;; *.png|*.gif|*.jpg) mv -v “$DIR/$1” $DIR/Downloads/_Pics ;; *.pdf|*.djvu) mv -v “$DIR/$1” $DIR/Downloads/_eBooks ;; *.zip) newDIR=”$DIR/Downloads/_ZIPs/${1%.*}” mkdir “$newDIR” sleep 20; while [ -f “$DIR/$1.part” ]; do sleep 5; done unzip “$DIR/$1” -d “$newDIR/” mv -v “$DIR/$1” “$newDIR/” chown -R testuser “$newDIR” ;; *) echo “ - None” ;; esac } &> /tmp/Download_Sort.log
Принцип его работы очень прост: файлы распознаются по расширениям (при желании сделать скрипт более «интеллектуальным» можно использовать команду file). Видеоролики перемещаются в папку _Video, картинки – в _Pics, документы PDF и DjVu – в _eBooks, Zip-архивы распаковываются в _ZIPs, файлы неизвестных форматов остаются на рабочем столе. Кроме этого, результат и ошибки обработки последнего файла сохраняются в /tmp/Download_Sort.log для проверки и тестирования работы скрипта. Сообщения службы incrond можно также просмотреть в системном журнале (/var/log/messages или аналогичном). Они имеют стандартный вид:
Jun 15 14:36:11 hostname incrond[4728]: (root) CMD (/usr/local/bin/Download_Sort.sh Pinguins.zip)
Теперь создадим /home/testuser/Desktop/Downloads и соответствующие поддиректории для разных типов файлов:
mkdir -p /home/testuser/Desktop/Downloads/_{Video,Pics,eBooks,ZIPs}
Установим права, необходимые для запуска скрипта и для нормальной работы пользователя с его каталогами:
chmod a+rx /usr/local/bin/Download_Sort.sh chown -R testuser /home/testuser/Desktop/Downloads
И, наконец, запустим службу, которая будет отслеживать для нас события:
/etc/init.d/incron start
Ее можно добавить и в автозапуск, если вы хотите, чтобы она самостоятельно стартовала после перезагрузки компьютера:
chkconfig incron on
Вот и всё: теперь можно сбрасывать на рабочий стол (в каталог /home/testuser/Desktop) различные файлы и смотреть, что с ними происходит.
Для наглядности, здесь приведен достаточно простой вариант скрипта. Желающие могут написать свой или расширить предложенный: например, добавив действия для RPM (установка или прописывание в локальный репозиторий), JAR (перенос на смартфон), EXE (проверка антивирусом), WAR (их – Tomcat’у), FLV (перекодирование в AVI), MP3 (в Ogg) и т. д., и т. п.
Кроме того, с помощью incron можно легко реализовать следующие идеи:
- Забыть про перезапуск сервисов после правки файлов конфигурации– этим займется incron, следящий за их изменением.
- Реализовать свою достаточно гибкую службу квот и аудита.
- Автоматически добавлять в свою web-галерею папку с картинками при копировании, например, в /srv/www/htdocs/images.
Уверен, вы сможете придумать и свои собственные способы для удобного использования данного инструмента.
Выбор есть всегда
Разумеется, ваше взаимодействие с Inotify не ограничивается iwatch с incron: в Linux есть весь необходимый инструментарий. Программистам на C обычно достаточно подключить заголовочный файл <linux/inotify.h>, разработчикам на Perl и Python пригодятся пакеты python-pyinotify и perl-Linux-Inotify2, web-программистам – php5‑inotify... модуль Inotify есть даже в Compiz! В скриптах удобно пользоваться утилитой inotifywait из пакета inotify-tools – как следует из названия, она позволяет приостановить сценарий в ожидании какого-либо события файловой системы. LXF