Журнал LinuxFormat - перейти на главную

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:


 #!/bin/bash
 DIR=/home/testuser/Desktop
 {
 echo “File: $icase “$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$newDIRsleep 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

Персональные инструменты
купить
подписаться
Яндекс.Метрика