Поиск по сайту:

Как выполнить задачу при добавлении нового файла в каталог в 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. Этот сценарий является хорошей отправной точкой для развертывания собственных рабочих процессов и автоматизации общих задач в вашей системе.