Как выполнить задачу при добавлении нового файла в каталог в Linux
В этом руководстве показано, как использовать события файловой системы Linux (notify), чтобы получать уведомления каждый раз, когда файл появляется в каталоге. Вы можете использовать их в качестве триггеров для автоматизации общих задач в вашей системе.
Мы собираемся написать скрипт, который следит за каталогом и обрабатывает новые добавляемые файлы. Каждый файл архивируется и перемещается в другой каталог, как только он обнаружен. Сценарий использует подсистему inotify через утилиту под названием inotify-tools. Но сначала давайте установим инструмент и поэкспериментируем.
Установка inotify-tools и gzip
Используйте apt-get
для установки этого пакета в вашу систему, если вы используете Ubuntu или другой дистрибутив на основе Debian. В других дистрибутивах Linux вместо этого используйте инструмент управления пакетами вашего дистрибутива Linux.
sudo apt-get install inotify-tools gzip
Эксперименты с inotify-tools
Давайте начнем с просмотра каталога и выяснения, какие события инициируются при поступлении новых файлов. Мы будем использовать инструмент под названием inotifywatch
, который является частью инструментов inotify-tools. Создайте новый каталог под названием «incoming»:
mkdir incoming
Начните просмотр этого каталога, выполнив следующую команду:
inotifywatch -v incoming
Это даст указание inotify отслеживать все события файловой системы во «входящем» каталоге. Параметр -v
заставляет инструмент распечатывать дополнительную информацию о том, что он делает. Мы не указали параметр времени ожидания (-t
), и команда будет продолжать собирать события, пока мы не выйдем с помощью CTRL+C. На данный момент наш терминал должен выглядеть примерно так:
Откройте новое окно терминала (или вкладку) и перейдите во входящий каталог. Используйте сенсорную команду, чтобы создать новый файл с именем «newfile».
cd incoming/ touch newfile
Теперь вернитесь в первое окно терминала и остановите inotifywatch, нажав CTRL+C.
На консоль будет передана таблица событий с указанием одного экземпляра «create», «open», «attrib» и «close_write». Эти четыре события произошли, когда мы использовали touch для создания нового файла, установили его атрибуты доступа к файлу, открыли его для записи нулевого завершающего символа, а затем закрыли его. Это лишь некоторые из множества событий, которые можно отслеживать в файловой системе с помощью инструментов inotify. Вы можете увидеть полный список на главной странице для inotifywatch.
Для наших целей нас интересуют только два события:
- «создать» — когда файл создается в целевом каталоге.
- moved_to — когда файл перемещается из другого места в целевой каталог.
Давайте снова попробуем inotifywatch, но на этот раз дадим ему указание отслеживать только эти два события. Запустите эту команду в первом окне терминала:
inotifywatch -v -e create -e moved_to incoming
Во втором окне или вкладке терминала попробуем создать новый файл, изменить его содержимое, а затем переместить файл из другого места в целевой каталог. Все эти команды запускаются из домашнего каталога.
touch incoming/created echo Testing123 >> incoming/created touch /tmp/created2 mv /tmp/created2 incoming/
Вернитесь к первому окну терминала и остановите inotifywatch, нажав CTRL+C. Мы увидим следующий вывод:
Учитывались только два события: создание файла с именем «created.txt» и перемещение существующего файла с именем «created2.txt». Все остальное, например изменение файла «created.txt», было проигнорировано.
Просмотр каталога и выполнение задачи
Теперь, когда мы знаем, за какими событиями следует следовать, мы можем использовать другой инструмент под названием inotifywait
, чтобы заблокировать выполнение до тех пор, пока файл не будет создан или перемещен в наш целевой каталог. Мы будем использовать те же аргументы, что и в случае с inotifywatch, а также укажем, как мы хотим, чтобы имя файла было отформатировано для использования в нашей задаче.
Прежде чем мы начнем, нам нужен каталог для хранения файлов, которые уже были обработаны. Создайте каталог под названием «processed»:
mkdir processed
Затем создайте новый скрипт с именем «watch-incoming.sh» и добавьте содержимое, указанное ниже:
#!/bin/bash TARGET=~/incoming/ PROCESSED=~/processed/ inotifywait -m -e create -e moved_to --format "%f" $TARGET \ | while read FILENAME do echo Detected $FILENAME, moving and zipping mv "$TARGET/$FILENAME" "$PROCESSED/$FILENAME" gzip "$PROCESSED/$FILENAME" done
Сценарий выполняет команду inotifywait
с параметром -m
. Это делает команду монитора изменений на неопределенный срок. Каждый раз, когда обнаруживается новое событие, имя файла передается команде чтения и вводится в переменную «FILENAME». Выполняется блок под циклом while, в котором файл сначала перемещается в «обрабатываемый» каталог, а затем сжимается. Исходный файл заменяется сжатым файлом, а имя файла заканчивается на «.gz».
Давайте предоставим права на выполнение этого скрипта и запустим его из нашего домашнего каталога.
chmod u+x watch-incoming.sh ./watch-incoming.sh
Откройте второе окно терминала и создайте новый файл в «входящем» каталоге. Перечислите содержимое как «входящего», так и «обработанного» каталога, чтобы увидеть результаты обнаружения события:
Необработанный текстовый файл, который мы скопировали во «входящий» каталог, был обнаружен скриптом, скопирован в «обработанный» и затем сжат с помощью gzip.
Теперь, когда мы можем отслеживать новые файлы, поступающие в каталог, мы можем выполнять некоторые интересные задачи. Например, мы могли бы добавлять водяные знаки к файлам изображений, сжимать необработанные видео в формат mp4 и даже загружать каждый новый файл, который мы видим, в корзину Amazon S3. Этот сценарий является хорошей отправной точкой для развертывания собственных рабочих процессов и автоматизации общих задач в вашей системе.