Сообщить об ошибке.

Подсистема ядра Inotify в Linux

Мониторинг файловой системы в реальном времени

Содержание:

Подсистема ядра Linux inotify позволяет отслеживать события файловой системы (создание, удаление, изменение файлов) в режиме реального времени. Это мощный инструмент для автоматизации задач, отладки и мониторинга.

Как работает inotify?

  • Механизм: Ядро генерирует события при изменениях в ФС, а приложения подписываются на эти уведомления.
  • Преимущества:
    • Не требует периодического сканирования (как find или du).
    • Минимальная нагрузка на систему.
    • Работает в реальном времени.

Установка inotify-tools

Для использования inotify через CLI нужны утилиты inotifywait и inotifywatch:

# Debian/Ubuntu
sudo apt install inotify-tools

# RHEL/CentOS/Fedora
sudo yum install inotify-tools

Основные команды

1. inotifywait - мониторинг событий

Формат вызова:

inotifywait [опции] путь

Примеры:

  • Мониторинг каталога на создание файлов:

    inotifywait -m /path/to/dir -e create
    
    • -m: Режим постоянного мониторинга (без выхода после первого события).
    • -e create: Отслеживать только событие создание.
  • Отслеживание нескольких событий:

    inotifywait -m /path/to/dir -e create,delete,modify
    
  • Рекурсивный мониторинг (включая подкаталоги):

    inotifywait -m -r /path/to/dir
    
  • Выполнение команды при событии:

    inotifywait -m /path/to/dir -e create |
    while read path action file; do
        echo "Создан файл: $file в $path"
    done
    
  • Автоматическое копирование новых файлов:

    inotifywait -m -r -e create --format '%w%f' /source |
    while read newfile; do
        cp "$newfile" /destination/
        echo "Скопирован: $newfile"
    done
    

2. inotifywatch - сбор статистики

Формат вызова:

inotifywatch [опции] путь

Примеры:

  • Статистика по событиям за 60 секунд:

    inotifywatch -v -e create,delete -t 60 /path/to/dir
    
    • -t 60: Мониторинг 60 секунд.
    • -v: Подробный вывод.

Ключевые события inotify

СобытиеОписание
accessФайл был прочитан.
modifyФайл был изменен.
attribИзменены метаданные (права).
close_writeФайл закрыт после записи.
close_nowriteФайл закрыт без записи.
openФайл открыт.
moved_fromФайл перемещен из каталога.
moved_toФайл перемещен в каталог.
createСоздан файл/каталог.
deleteУдален файл/каталог.
delete_selfУдален сам отслеживаемый объект.

Опция --format для явного указания формата вывода:

inotifywait -m /docs -e modify --format "%w %e %f" |
while read path action file; do
    # Теперь $file будет содержать имя с пробелами
    if [[ "$file" == "important.docx" ]]; then
        cp "$path$file" /backup/
    fi
done
  • %w - путь (всегда с /)
  • %e - событие
  • %f - имя файла (включая пробелы)

Полный разбор формата inotifywait

СимволОписаниеПример вывода
%wПуть к каталогу (с /)/docs/
%eСобытиеMODIFY
%fИмя файлаimportant.docx
%TВремя в формате ISO 86012023-10-05T14:30:45

Пример с датой:

inotifywait -m /docs --format "%T %w %e %f" |
while read datetime path action file; do
    echo "[$datetime] Событие: $action, файл: $file"
done

Ограничения inotify

  1. Лимиты ядра:

    • Максимальное количество наблюдателей (fs.inotify.max_user_watches).
    • Максимальное количество экземпляров (fs.inotify.max_user_instances).

    Проверка лимитов:

    sysctl fs.inotify
    

    Увеличение лимитов (добавить в /etc/sysctl.conf):

    fs.inotify.max_user_watches = 524288
    fs.inotify.max_user_instances = 8192
    

    Применить: sysctl -p.

  2. Рекурсивный мониторинг:

    • Для глубоких деревьев каталогов может потребоваться много наблюдателей.
    • Альтернатива: использовать inotifywait с -r и фильтровать события.
  3. События перемещения:

    • При перемещении файла между ФС генерируются delete и create, а не move.

Inotify - это стандарт де-факто для мониторинга ФС в Linux. Он эффективен, прост в использовании и интегрируется в любые сценарии автоматизации. Для большинства задач достаточно inotify-tools, но для сложных случаев рассмотрите альтернативы.

Как inotifywait остается запущенным для мониторинга?

Как все устроено на примере команды: inotifywait -m /path/to/dir -e create,delete,modify

Ключевой флаг -m (monitor mode)

  • Без -m: По умолчанию inotifywait завершает работу после первого события.
  • С -m: Команда переходит в режим постоянного мониторинга и не завершается, пока её не прервут вручную (например, Ctrl+C).

Технический процесс работы

  1. Инициализация:

    • inotifywait создает экземпляр inotify через системный вызов inotify_init().
    • Добавляет наблюдение за каталогом /path/to/dir с помощью inotify_add_watch(), указывая события: create, delete, modify.
  2. Ожидание событий:

    • Команда "засыпает" в режиме ожидания (используя системный вызов read() или poll()).
    • Ядро Linux уведомляет inotifywait о событиях в реальном времени (без опроса ФС).
  3. Вывод событий:

    • При возникновении события (например, создание файла) inotifywait выводит информацию в stdout:
      /path/to/dir/ CREATE newfile.txt
      
    • После этого она возвращается в режим ожидания следующего события.

Почему команда не завершается?

  • Бесконечный цикл: Флаг -m запускает внутренний цикл, который обрабатывает события до явного прерывания.
  • Отсутствие таймаута: Нет ограничений по времени или количеству событий.
  • Работа в фоне: Даже если запустить команду в фоновом режиме (&), она продолжит мониторинг.

Пример работы в терминале

$ inotifywait -m /tmp -e create,delete,modify

Вывод при событиях:

/tmp/ CREATE test.txt    # Создан файл test.txt
/tmp/ MODIFY test.txt    # Файл изменен
/tmp/ DELETE test.txt    # Файл удален

Команда будет ждать новые события бесконечно, пока вы не нажмете Ctrl+C.

Как использовать в скриптах?

Вариант 1: Цикл while

inotifywait -m /path/to/dir -e create,delete,modify |
while read path action file; do
    echo "Событие: $action над файлом $file в $path"
    # Ваши действия здесь
done
  • Команда передает каждое событие в цикл while.
  • Цикл обрабатывает события и возвращается к ожиданию следующего.

Вариант 2: Запуск в фоне

inotifywait -m /path/to/dir -e create > events.log &
  • Команда работает в фоне, записывая события в файл events.log.
  • Чтобы остановить: kill %1 (где %1 — ID фонового процесса).

Как остановить мониторинг?

  • В терминале: Нажмите Ctrl+C.
  • В скрипте: Используйте сигнал SIGTERM:
    # Запуск в фоне
    inotifywait -m /path/to/dir &
    
    # Сохраняем PID процесса
    PID=$!
    
    # Остановка позже
    kill $PID
    

Особенности режима -m

ПараметрПоведение
Без -mЗавершается после первого события.
С -mРаботает бесконечно, пока не прервана.
ВыводКаждое событие выводится в новой строке.
РесурсыМинимальная нагрузка (ядро уведомляет о событиях, а не опрашивает ФС).
РекурсияДля мониторинга подкаталогов добавьте -r (но это увеличит нагрузку).

Примеры сценариев

Для остановки всегда используйте Ctrl+C или команду kill. Это делает inotifywait идеальным инструментом для мониторинга ФС в реальном времени.

Автоматическое резервное копирование при изменении файла

inotifywait -m /docs -e modify |
while read path action file; do
    if [[ "$file" == "important.docx" ]]; then
        cp "$path$file" /backup/
        echo "Резервная копия создана: $(date)"
    fi
done

Очистка каталога при появлении новых файлов

inotifywait -m /uploads -e create |
while read; do
    rm -f /uploads/*
    echo "Очищено в $(date)"
done

Перезапуск сервиса при изменении конфига

inotifywait -m -e modify /etc/nginx/nginx.conf |
while read; do
    systemctl reload nginx
    echo "Nginx перезапущен"
done

Мониторинг логов в реальном времени

inotifywait -m -e modify /var/log/syslog |
while read; do
    tail -n 1 /var/log/syslog
done

Альтернативы inotify

entr (запуск команд при изменении файлов)

# Установка
sudo apt install entr

# Пример: перезапуск сервиса при изменении конфигов
echo /etc/nginx/*.conf | entr -r systemctl reload nginx

watch (периодическое выполнение команд)

# Проверка содержимого каталога каждые 2 секунды
watch -n 2 'ls -l /path/to/dir'

systemd.path (мониторинг через systemd)

Пример юнита для автоматического запуска скрипта при появлении файлов:

# /etc/systemd/system/monitor.path
[Unit]
Description=Monitor directory

[Path]
PathModified=/path/to/dir
Unit=monitor.service

[Install]
WantedBy=multi-user.target
# /etc/systemd/system/monitor.service
[Unit]
Description=React to changes

[Service]
ExecStart=/path/to/script.sh
systemctl enable --now monitor.path