Voglio eseguire automaticamente uno script ogni volta che nuovi file vengono copiati in una directory specifica. In altre parole, c'è un modo in Linux di "guardare" una directory per le modifiche e quindi eseguire qualcosa in risposta alla modifica?
Voglio eseguire automaticamente uno script ogni volta che nuovi file vengono copiati in una directory specifica. In altre parole, c'è un modo in Linux di "guardare" una directory per le modifiche e quindi eseguire qualcosa in risposta alla modifica?
Risposte:
Se si ha la fortuna di essere su una distribuzione basata su Debian, apt-get install dnotify
. Altre distribuzioni probabilmente hanno qualcosa di simile: cerca il dnotify
nome.
dnotify è un semplice programma basato sull'API dnotify del kernel 2.4.19 + di Linux. dnotify può eseguire un comando specificato ogni volta che cambia il contenuto di una directory specifica. Viene eseguito dalla riga di comando e accetta due argomenti: una o più directory da monitorare e un comando da eseguire ogni volta che una directory è cambiata. Le opzioni controllano quali eventi attivare: quando un file è stato letto nella directory, quando ne è stato creato uno, eliminato e così via.
Se vuoi gestirlo nel tuo programma, dnotify è anche l'API che vuoi usare.
emerge inotify-tools
Puoi eseguire uno script con gli strumenti inotify, qualcosa del genere. Controllerà la directory per le modifiche ai file modificati, nuovi file e file eliminati, quindi eseguirà lo script.
#!/bin/sh
while inotifywait -e modify -e create -e delete /home/me/code; do
rsync [options] /home/me/code/ /media/nfs/code/
done
incron è fondamentalmente quello che vuoi, penso. Usa inotify come meccanismo di notifica (che, come altri hanno sottolineato, sostituisce dnotify), ma non richiede uno script che viene eseguito continuamente, usando inotifywait o simili (sebbene, ovviamente, il demone incron sia sempre in esecuzione). I "crontab" a livello di sistema e i "crontab" dell'utente sono supportati in modo simile al cron standard, ma anziché specificare i tempi come trigger, inotificare eventi e vengono utilizzati i nomi di file / directory.
incron è confezionato per molte distribuzioni, tra cui Ubuntu e Debian, credo.
entr è lo strumento di notifica file più semplice e compostabile che abbia mai visto. Il suo utilizzo è ottimizzato per la visione di file piuttosto che di directory, ma può anche risolvere il tuo caso.
Per rilevare e agire sul file aggiunto, combinalo con altri strumenti come ad es make
. entr
non invia il nome o qualcosa del genere, esegue semplicemente ciò che gli hai detto di eseguire.
Per verificare la presenza di file aggiunti in una directory:
## 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
Se vuoi agire anche quando cambia un file esistente:
## 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
... ed è qui che il meccanismo del ciclo risulta utile, poiché l' find
espressione verrà eseguita nuovamente se viene aggiunto un file.
Se vuoi una migliore gestione degli errori e vuoi assicurarti che le cose vengano eseguite solo una volta per file aggiunto / rimosso, le cose diventano un po 'eccentriche, ma per questi semplici casi è geniale.
EDIT: Se vuoi farlo a livello di sistema, qualcosa come incron , aggiungi lo script al tuo gestore dei processi preferito (come s6 , runit , systemd o sysvinit e salta il loop:
#!/bin/bash
exec entr -d do_stuff < <(find /path/to/directory_to_watch/ -path /path/to/directory_to_watch/*)
La exec
sostituzione di processo e ( <(...)
) sono importanti quando si esegue da un gestore di processo, per gestire correttamente la segnalazione (cioè per togliere la shell).