Monitorowanie zmian w katalogu i uruchamianie skryptu przy pomocy (systemd.path
i inotifywait
)
systemd.path
i inotifywait
W wielu przypadkach przydaje się możliwość monitorowania zmian w katalogu, np. aby:
- wysyłać powiadomienie na Discorda
- wykonywać backup po zmianie
- uruchamiać automatyczne skrypty CI/CD
- integrować z systemami monitoringu
Przedstawię tutaj dwie metody:
1️⃣ systemd.path
— prosty monitoring katalogu
2️⃣ inotifywait
— pełny monitoring rekurencyjny
systemd.path
— prosta metoda dla katalogu głównego
systemd
od wersji 215 posiada typ unitów .path
, które pozwalają na monitorowanie pliku lub katalogu.
W momencie tworzenia tego wpisu systemd jest w wersji 257, zatem funkcjonalność jest stabilna.
Jak to działa?
PathModified=/path
- wykrywa zmianę w danym katalogu (np. dodanie/ usunięcie pliku lub podkatalogu)- nie monitoruje rekurencyjnie - nie zobaczy zmian wewnątrz podkatalogów
Note
PathModified
monitoruje zmianę samego katalogu, czyli np.:
- utworzenie nowego pliku
- usunięcie pliku
- utworzenie nowego podkatalogu
- usunięcie podkatalogu
Nie wykryje natomiast zmian w plikach wewnątrz podkatalogów.
Przykład: katalog bez podkatalogów
Załóżmy mamy katalog /var/www/html/
.
W nim znajdują się np.:
Implementacja krok po kroku
Skrypt powiadamiający
Plik /usr/local/bin/discord_notify.sh
:
#!/bin/bash
source ~/.bashrc
directory="/var/www/html"
curl -H "Content-Type: application/json" -X POST -d "{\"content\": \"Change detected in $directory\"}" "$DISCORD_WEBHOOK_URL"
Ustawienie zmiennej środowiskowej
Ustaw zmienną środowiskową `DISCORD_WEBHOOK_URL` w pliku `~/.bashrc` lub innym odpowiednim miejscu.
W przypadku zmiennej środowiskowej, możesz wykorzystać również inne pliki/metody, bashrc nie zawsze może się sprawdzić.
Jeśli użyjesz w konfiguracji unit'a EnvironmentFile, bashrc nie będzie odczytany z uwagi na sposób w jaki systemd uruchamia usługi.
Linux daje tutaj wiele możliwości, zmienne można definiowac na serwerza jak i w bardziej złożonych systemach, w konfiguracji GitHub Actions, GitLab CI/CD, Jenkins, itp.
Przedstawiony przykład jest jednym z wielu sposobów.
Nadajemy uprawnienia:
Unit .service
Plik /etc/systemd/system/discord-notify.service
:
[Unit]
Description=Sending Discord notification on changes in directory
[Service]
Type=oneshot
ExecStart=/usr/local/bin/discord_notify.sh
[Install]
WantedBy=multi-user.target
Unit .path
Plik /etc/systemd/system/discord-notify.path
:
[Unit]
Description=Checking changes in /var/www/html
[Path]
PathModified=/var/www/html
[Install]
WantedBy=multi-user.target
Uruchomienie
Test
Przykładowe operacje i wynik:
Operacja | Skrypt się uruchomi? |
---|---|
touch /var/www/html/file1 |
✅ TAK |
rm /var/www/html/file1 |
✅ TAK |
mkdir /var/www/html/dirxx |
✅ TAK |
touch /var/www/html/dirxx/file1 |
❌ NIE |
rm /var/www/html/dirxx/file1 |
❌ NIE |
Warning
**`systemd.path` nie monitoruje zmian wewnątrz podkatalogów.**
Zmiana w `/var/www/html/dirxx/file.txt` nie uruchomi skryptu.
Jak działa PathExistsGlob
Dyrektywa PathExistsGlob
pozwala określić wzorzec (glob), który systemd będzie sprawdzać.
Jeśli co najmniej jeden plik lub katalog pasuje do wzorca, to powiązany .service
zostanie uruchomiony.
Mechanizm działa jak funkcja glob()
w bashu:
*
— dowolny ciąg znaków (ale tylko jeden poziom katalogu)- np.
/opt/www/*
— wszystko w katalogu/opt/www/
(przy założeniu, że katalog jest pusty) - np.
/backup/*.tar.gz
— wszystkie pliki.tar.gz
w katalogu/backup/
Ograniczenia
PathExistsGlob
nie śledzi zmian w plikach (np. modyfikacji ich zawartości) — tylko sprawdza, czy pasujący plik lub katalog istnieje.- Wzorce rekurencyjne typu
**
(np./opt/www/**/*.txt
) nie są obsługiwane wsystemd.path
. Jeśli potrzebujesz śledzenia zmian rekurencyjnych, lepszym wyborem jestinotifywait
.
Przykład użycia
Załóżmy, że mamy katalog /var/incoming/
, do którego proces lub skrypt wrzuca pliki .done
.
[Unit]
Description=Check if .done exists in /var/incoming
[Path]
PathExistsGlob=/var/incoming/*.done
[Install]
WantedBy=multi-user.target
Gdy tylko pojawi się nowy plik *.done
, np.:
uruchomi się powiązany .service
.
Inny przykład — katalog /var/www/
Uruchomi .service
w momencie, gdy w katalogu /opt/www/
pojawi się:
- dowolny plik, np.
index.html
- dowolny katalog, np.
images/
PathExistsGlob=/opt/www/*
działa tylko na bezpośrednie podkatalogi folderu /var/www/
.
Zmiany w podkatalogach (/opt/www/images/photo.jpg
) nie są bezpośrednio śledzone - jeżeli podkatalog powstanie (mkdir images
), to zadziała.
Podsumowanie
PathExistsGlob
to szybki sposób na reagowanie na pojawienie się plików lub katalogów:
- ✅ proste monitorowanie katalogu
- ✅ reagowanie na nowe pliki
- ❌ brak wsparcia dla pełnej rekurencji
- ❌ brak monitorowania modyfikacji lub usunięcia plików
Dla pełnego rekurencyjnego śledzenia katalogu i zmian w plikach lepszym wyborem będzie narzędzie inotifywait
.
inotifywait
- monitoring rekurencyjny
Jeżeli chcesz monitorować:
- katalog + podkatalogi
- dowolne zmiany w plikach
- utworzenie/usunięcie folderów i plików
→ systemd.path
nie wystarczy.
Potrzebne będzie narzędzie: inotifywait
.
Instalacja
lub
Skrypt monitorujący
Plik /usr/local/bin/discord_watch.sh
:
#!/bin/bash
WATCH_DIR="/var/www/html"
inotifywait -mrq -e close_write,move,create,delete "$WATCH_DIR" | while read -r path action file; do
curl -H "Content-Type: application/json" -X POST -d "{\"content\": \"Change: ${action} -> ${path}${file}\"}" "$DISCORD_WEBHOOK_URL"
done
Nadajemy uprawnienia:
Unit systemd dla discord_watch.sh
Plik /etc/systemd/system/discord-watch.service
:
[Unit]
Description=Recursive monitoring of /var/www/html
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/discord_watch.sh
Restart=always
[Install]
WantedBy=multi-user.target
Uruchomienie
Test
Przykładowe operacje i wynik:
Operacja | Skrypt się uruchomi? |
---|---|
touch /var/www/html/new_file |
✅ TAK |
rm /var/www/html/file1 |
✅ TAK |
mkdir /var/www/html/dir1 |
✅ TAK |
touch /var/www/html/dir1/file1 |
✅ TAK |
rm /var/www/html/dir1/file1 |
✅ TAK |
Note
`inotifywait` pozwala na pełny monitoring rekurencyjny katalogu i wszystkich jego podkatalogów.
Możemy monitorować dowolne zdarzenia, np.: `create`, `delete`, `move`, `close_write`, `attrib` (zmiana metadanych).
Podsumowanie
Cecha | systemd.path | inotifywait + systemd.service |
---|---|---|
Wbudowany w systemd | ✅ | ❌ (wymaga inotify-tools ) |
Rekurencja (podkatalogi) | ❌ NIE | ✅ TAK |
Monitorowanie zmian w plikach | ✅ TAK | ✅ TAK |
Monitorowanie zmian w podkatalogach | ❌ NIE | ✅ TAK |
Wydajność | bardzo dobra | bardzo dobra |
Kiedy co stosować?
- ✅
systemd.path
- jeśli katalog nie ma podkatalogów lub interesuje nas tylko sama struktura katalogu - ✅
inotifywait
- jeżeli potrzebujemy pełnego monitorowania całego drzewa katalogów (np./var/www/html
lub/opt/data
etc.)
Uwagi praktyczne
- Edytory plików (np.
vim
,nano
) mogą powodować tymczasowe operacje, które będą widziane jakocreate
imove
. Warto w takich przypadkach ograniczyć typy eventów lub stosować prosty filtr w skrypcie. inotifywait
działa bardzo szybko i jest mało zasobożerne. W przypadku dużych katalogów warto testować wydajność.