Wykonaj skrypt / program po zmianie pliku

6

Czy istnieje sposób na ustawienie wyzwalacza w pliku, aby za każdym razem, gdy plik był zmieniany, skrypt lub program był uruchamiany?

Znalazłem tylko ten mechanizm w skrypcie powłoki, ale chciałbym wiedzieć, czy istnieje taki mechanizm w systemie operacyjnym (aby nie musiałem ręcznie uruchamiać programu działającego w tle). Rozwiązaniem opartym na systemie operacyjnym byłoby zadanie cron uruchamiane co kilka sekund, ale nie wydaje mi się to odpowiednim rozwiązaniem.

To jest dla Debiana, btw.

Dzięki za pomoc.

podstępny
źródło

Odpowiedzi:

8

jedną z opcji jest podsystem inotify jądra Linux:

inotify to podsystem jądra Linux, który rozszerza systemy plików, aby zauważać zmiany w systemie plików i zgłaszać te zmiany aplikacjom

ale ponieważ inotifyjest to jądro, potrzebujesz czegoś w przestrzeni użytkownika, aby z niego skorzystać:

Demon inotify cron (incrond) to demon, który monitoruje zdarzenia w systemie plików i wykonuje polecenia zdefiniowane w tabelach systemu i użytkowników. Jego użycie jest ogólnie podobne do crona (8).

Gamin to system monitorowania plików i katalogów, który niezależnie wdraża podzbiór FAM, File Alteration Monitor. Działając jako usługa, pozwala na wykrycie modyfikacji pliku lub katalogu. gam_server działa jako demon dla Gamina.

inoticoming - wyzwalaj akcje, gdy pliki trafią do katalogu przychodzącego

na askubuntu pojawiła się odpowiedź na podobne pytanie:

https://askubuntu.com/a/43848/1223

akira
źródło
1
Żeby Cię poinformować: teraz używam inotify w połączeniu z incron, który działa dla mnie idealnie. Wiem, że incron jest wciąż w fazie alfa, ale wykonuje naprawdę dobrą robotę. Dziękuję bardzo za tę wspaniałą radę!
cyphorious
2

Innym szybkim i brudnym sposobem na to jest użycie inotifywaitpakietu inotify-tools (na fedorze).

Bardziej podoba mi się ta metoda, ponieważ możesz to wszystko zrobić z jednego wiersza poleceń bash. Często używam tego, gdy piszę małe programy, aby zobaczyć wyniki tego, co właśnie zapisałem.

while [[ 1 ]]; do inotifywait -e modify <filename>; make && ./helloworld; done
Marioux
źródło
1

Argumentowałbym, że mechanizm tego w skrypcie powłoki jest rozwiązaniem całkowicie adekwatnym i że mechanizm oparty na systemie operacyjnym (aby nie musiałem ręcznie uruchamiać programu działającego w tle) oznacza po prostu umieszczenie tego rozwiązania w procesie manager jak s6 , runit , jednostka systemowa , a nawet wpis inittab, jeśli korzystasz z systemu sysvinit.

Niezależnie od mechanizmu utrzymywania go, lubię entr do oglądania plików. Prosty do rzeczy, łatwy do skomponowania (np. Trywialny w menedżerze procesów).

Oto skrypt do oglądania /path/to/filei uruchamiania, /usr/local/bin/do_stuffgdy się zmienia:

#!/bin/bash
exec entr /usr/local/bin/do_stuff < <(echo /path/to/file)

To wszystko. Umieść to w runpliku runit lub s6, umieść w ExecStartwierszu jednostki systemowej lub wywołaj ten skrypt z linii w inittab. Chociaż jeśli go włożysz inittab, prawdopodobnie chcesz coś sleepgdzieś dodać , ponieważ sysvinit nie ogranicza procesów, które kończą się niepowodzeniem natychmiast z powodu błędów ortograficznych, brakujących plików itp.


Dlaczego nie tylko echo /path/to/file | entr /usr/local/bin/do_stuff? Podczas zarządzania procesem ważne jest, aby zarządzany proces znajdował się bezpośrednio pod zwierzchnikiem, tak aby zachowywał się poprawnie przy wyłączeniu. Jeśli powłoka działa pod przełożonego, powłoka złapie każdy TERM, INTczy KILLsygnały raczej niż proces jest uruchomiony, a to nie będzie przekazać je dalej. Lub zakończy działanie i pozostawi proces osierocony. execusuwa powłokę z łańcucha procesu. ( execpo prawej stronie |nie ma znaczenia)

Lub po prostu użyj powłoki, która nigdy nie stawia się na środku, wykonaj :

#!/bin/execlineb
pipeline -d {
  echo /path/to/file
} entr /usr/local/bin/do_stuff
clacke
źródło