Jak wykonać zadanie po dodaniu nowego pliku do katalogu w systemie Linux

Ten samouczek pokaże, jak używać zdarzeń systemu plików Linuksa (powiadamiania), aby otrzymywać powiadomienia za każdym razem, gdy plik pojawia się w katalogu. Można ich użyć jako wyzwalaczy do automatyzacji typowych zadań w systemie.

Napiszemy skrypt, który będzie obserwował katalog i działał na nowych plikach, które są dodawane. Każdy plik jest zgzipowany i przenoszony do innego katalogu, gdy tylko zostanie wykryty. Skrypt korzysta z podsystemu inotify za pośrednictwem narzędzia o nazwie inotify-tools. Ale najpierw zainstalujmy narzędzie i poeksperymentujmy.

Instalowanie inotify-tools i gzip

Użyj apt-get, aby zainstalować ten pakiet w swoim systemie, jeśli używasz Ubuntu lub innej dystrybucji opartej na Debianie. W innych dystrybucjach Linuksa użyj zamiast tego narzędzia do zarządzania pakietami dystrybucji Linuksa.

sudo apt-get install inotify-tools gzip

Eksperymentowanie z narzędziami inotify

Zacznijmy od obejrzenia katalogu i sprawdzenia, jakie zdarzenia są inicjowane po nadejściu nowych plików. Użyjemy narzędzia o nazwie inotifywatch, które jest częścią inotify-tools. Utwórz nowy katalog o nazwie „przychodzące”:

mkdir incoming

Rozpocznij obserwację tego katalogu, wykonując następujące polecenie:

inotifywatch -v incoming

Poinstruuje to inotify, aby obserwował wszystkie zdarzenia systemu plików w katalogu „incoming”. Opcja -v sprawia, że ​​narzędzie drukuje dodatkowe informacje o tym, co robi. Nie określiliśmy opcji limitu czasu (-t), a polecenie będzie zbierać zdarzenia, dopóki nie wyjdzie z CTRL + C. W tym momencie nasz terminal powinien wyglądać mniej więcej tak:

Otwórz nowe okno terminala (lub kartę) i przejdź do katalogu poczty przychodzącej. Użyj polecenia dotykowego, aby utworzyć nowy plik o nazwie „nowy plik”.

cd incoming/
touch newfile

Teraz wróć do pierwszego okna terminala i zatrzymaj inotifywatch, naciskając CTRL + C.

Tabela zdarzeń zostanie wyświetlona na konsoli, wskazując jedno wystąpienie „Utwórz”, „Otwórz”, „Atrybut” i „Zamknij_Pisz”. Te cztery zdarzenia miały miejsce, gdy użyliśmy touch do utworzenia nowego pliku, ustawiliśmy jego atrybuty dostępu do pliku, otworzyliśmy go w celu zapisania znaku kończącego wartość null, a następnie zamknęliśmy. To tylko kilka z wielu zdarzeń, które można monitorować w systemie plików za pomocą narzędzi inotify-tools. Możesz zobaczyć pełną listę na stronie głównej inotifywatch.

Dla naszych celów interesują nas tylko dwa wydarzenia:

„Create” – gdy plik jest tworzony w katalogu docelowym.
„Move_to” – gdy plik jest przenoszony z innej lokalizacji do katalogu docelowego.

Spróbujmy ponownie inotifywatch, ale tym razem poinstruujmy go, aby monitorował tylko te dwa zdarzenia. Uruchom to polecenie w pierwszym oknie terminala:

inotifywatch -v -e create -e moved_to incoming

W drugim oknie lub karcie terminala spróbujmy utworzyć nowy plik, zmienić jego zawartość, a następnie przenieść plik z innej lokalizacji do katalogu docelowego. Wszystkie te polecenia są uruchamiane z katalogu domowego.

touch incoming/created
echo Testing123 >> incoming/created
touch /tmp/created2
mv /tmp/created2 incoming/

Wróć do pierwszego okna terminala i zatrzymaj inotifywatch, naciskając CTRL + C. Zobaczymy następujący wynik:

Zliczono tylko dwa zdarzenia: utworzenie pliku o nazwie „created.txt” i przeniesienie istniejącego pliku o nazwie „created2.txt”. Wszystko inne, na przykład modyfikacja pliku „created.txt”, zostało zignorowane.

Obserwowanie katalogu i wykonywanie zadania

Teraz, gdy wiemy, jakie zdarzenia należy obserwować, możemy użyć innego narzędzia o nazwie inotifywait, aby zablokować wykonywanie, dopóki plik nie zostanie utworzony lub przeniesiony do naszego katalogu docelowego. Użyjemy tych samych argumentów, co w przypadku inotifywatch, a także określimy, w jaki sposób chcemy sformatować nazwę pliku do użycia w naszym zadaniu.

Zanim zaczniemy, potrzebujemy katalogu do przechowywania plików, które zostały już przetworzone. Utwórz katalog o nazwie „przetworzone”:

mkdir processed

Następnie utwórz nowy skrypt o nazwie „watch-incoming.sh” i dodaj zawartość wymienioną poniżej:

#!/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

Skrypt wykonuje polecenie inotifywait z opcją -m. To sprawia, że ​​monitor poleceń zmienia się w nieskończoność. Za każdym razem, gdy wykrywane jest nowe zdarzenie, nazwa pliku jest przekazywana do polecenia odczytu i wprowadzana do zmiennej „FILENAME”. Wykonywany jest blok znajdujący się pod pętlą while, w którym plik jest najpierw przenoszony do katalogu „przetworzonego”, a następnie zgzipowany. Oryginalny plik jest zastępowany plikiem skompresowanym, a nazwa pliku kończy się na „.gz”.

Udzielmy uprawnień do wykonywania tego skryptu i uruchommy go z naszego katalogu domowego.

chmod u+x watch-incoming.sh
./watch-incoming.sh

Otwórz drugie okno terminala i utwórz nowy plik w katalogu „przychodzące”. Wypisz zawartość zarówno katalogu „przychodzące”, jak i „przetworzone”, aby zobaczyć wyniki wykrytego zdarzenia:

Surowy plik tekstowy, który skopiowaliśmy do katalogu „incoming”, został wykryty przez skrypt, skopiowany do „przetworzonego”, a następnie skompresowany przy użyciu programu gzip.

Możemy teraz wykonać kilka interesujących zadań, gdy jesteśmy w stanie obserwować nowe pliki docierające do katalogu. Na przykład moglibyśmy dodać znak wodny do plików graficznych, skompresować surowe filmy do formatu mp4, a nawet przesłać każdy nowy plik, który widzimy do zasobnika Amazon S3. Ten skrypt jest dobrym punktem wyjścia do zmiany własnych przepływów pracy i automatyzacji typowych zadań w systemie.