Wie kann ich ein Skript automatisch ausführen, wenn sich der Inhalt eines Verzeichnisses unter Linux ändert?

17

Ich möchte automatisch ein Skript ausführen, wenn neue Dateien in ein bestimmtes Verzeichnis kopiert werden. Mit anderen Worten, gibt es in Linux eine Möglichkeit, ein Verzeichnis auf Änderungen zu "beobachten" und dann als Reaktion auf die Änderung etwas auszuführen?

GeneQ
quelle
Diese Diskussion wurde auf jeder Seite Stack gehalten;) siehe superuser.com/questions/181517/... stackoverflow.com/questions/4380527/... usw.
masterxilo

Antworten:

17

Wenn Sie Glück haben, auf einer Debian-basierte Distribution zu sein apt-get install dnotify. Andere Distributionen haben wahrscheinlich etwas Ähnliches - suchen Sie nach dem dnotifyNamen.

dnotify ist ein einfaches Programm, das auf der dnotify-API von Linux-Kernel 2.4.19 + basiert. dnotify kann jedes Mal einen bestimmten Befehl ausführen, wenn sich der Inhalt eines bestimmten Verzeichnisses ändert. Es wird über die Befehlszeile ausgeführt und benötigt zwei Argumente: ein oder mehrere zu überwachende Verzeichnisse und einen Befehl, der ausgeführt wird, wenn sich ein Verzeichnis geändert hat. Die Optionen steuern, welche Ereignisse ausgelöst werden sollen: wann eine Datei im Verzeichnis gelesen, wann eine erstellt, gelöscht usw. wurde.

Wenn Sie dies in Ihrem eigenen Programm erledigen möchten, ist dnotify auch die API, die Sie verwenden möchten.

MikeyB
quelle
4
@ MikeB, nachdem Sie Googeln dnotify vorgeschlagen haben, habe ich stattdessen inotify verwendet, was anscheinend übersteigt. Vielen Dank, dass Sie mir die richtige Richtung gezeigt haben. Apt-Get installieren Inotify-Tools
GeneQ
7
@GeneQ, inotify hat dnotify ersetzt.
David
1
Ebenfalls auf Gentoo:emerge inotify-tools
James Sneeringer
Ja, ich wollte sagen, Kernel 2.4.19 ist ein bisschen uralt ;-) Inotify ist der richtige Weg.
David Z
Oh ja ... ich habe vergessen, was neuer war :)
MikeyB
12

Sie können ein Skript mit den inotify-Werkzeugen ausführen. Es überwacht das Verzeichnis auf Änderungen an geänderten Dateien, neuen Dateien und gelöschten Dateien und führt dann das Skript aus.

#!/bin/sh
while inotifywait -e modify -e create -e delete /home/me/code; do
    rsync [options] /home/me/code/ /media/nfs/code/ 
done
user7119
quelle
Berücksichtigen Sie nur, dass inotifywait das Quellverzeichnis während des Kopierens NICHT sieht und diese Änderungen erst nach Abschluss des Kopiervorgangs kopiert werden, wenn weitere Änderungen vorgenommen wurden. Wahrscheinlich kein Problem.
Raúl Salinas-Monteagudo
Wie können Sie dies im Daemon-Modus ausführen?
Chris F
4

incron ist im Grunde was du willst, denke ich. Es verwendet inotify als Benachrichtigungsmechanismus (der dnotify, wie bereits erwähnt, ersetzt), erfordert jedoch kein Skript, das kontinuierlich ausgeführt wird und inotifywait oder ähnliches verwendet (obwohl der Incron-Dämon natürlich die ganze Zeit ausgeführt wird). Systemweite 'crontabs' und 'crontabs' von Benutzern werden auf ähnliche Weise wie bei Standard-Cron unterstützt, aber anstatt Zeiten als Trigger anzugeben, werden inotify-Ereignisse und Datei- / Verzeichnisnamen verwendet.

Ich glaube, dass Incron für viele Distributionen, einschließlich Ubuntu und Debian, gepackt ist.

Andrew Ferrier
quelle
0

Es gibt nur für diesen Zweck eine Software, autoenv. Vielleicht möchten Sie sie überprüfen.

DukeLion
quelle
0

entr ist das einfachste und komponierbarste Tool zur Benachrichtigung von Dateien, das ich je gesehen habe. Seine Verwendung ist eher für das Ansehen von Dateien als von Verzeichnissen optimiert, kann aber auch Ihren Fall lösen.

Um die hinzugefügte Datei zu erkennen und zu bearbeiten, kombinieren Sie sie mit anderen Tools wie z make. entrSendet den Namen oder ähnliches nicht, läuft einfach so, wie Sie es befohlen haben.

So suchen Sie in einem Verzeichnis nach hinzugefügten Dateien:

## entr exits with rc=0 when terminated
## rc=1 when watched files go away or don't exist to begin with
## rc=2 when new files arrive in watched directories
until echo /path/to/directory_to_watch | entr -d do_stuff
do sleep 1; done

Wenn Sie auch handeln möchten, wenn sich eine vorhandene Datei ändert:

## Here's why it comes in handy that entr exits when new files are added --
## find gets re-run.
until find /path/to/directory_to_watch/ -path /path/to/directory_to_watch/* |
    entr -d do_stuff
do sleep 1; done

... und hier ist der Schleifenmechanismus nützlich, da der findAusdruck erneut ausgeführt wird, wenn eine Datei hinzugefügt wird.

Wenn Sie eine bessere Fehlerbehandlung wünschen und sicherstellen möchten, dass die Dinge nur einmal pro hinzugefügter / entfernter Datei ausgeführt werden, werden die Dinge etwas eigenartig, aber für diese einfachen Fälle ist es brillant.


BEARBEITEN: Wenn Sie dies auf Systemebene tun möchten, zum Beispiel mit Incron , fügen Sie das Skript einfach Ihrem bevorzugten Prozessmanager hinzu (wie s6 , runit , systemd oder sysvinit) und überspringen Sie die Schleife:

#!/bin/bash
exec entr -d do_stuff < <(find /path/to/directory_to_watch/ -path /path/to/directory_to_watch/*)

Die execund die Prozessersetzung ( <(...)) sind wichtig, wenn ein Prozessmanager ausgeführt wird, um die Signalisierung ordnungsgemäß zu handhaben (dh um die Shell aus dem Weg zu räumen).

klappern
quelle