Je souhaite exécuter un script shell lorsqu'un fichier ou un répertoire spécifique est modifié.Sous Linux, comment exécuter un script shell lorsqu'un fichier ou un répertoire change
Comment puis-je facilement faire cela?
Je souhaite exécuter un script shell lorsqu'un fichier ou un répertoire spécifique est modifié.Sous Linux, comment exécuter un script shell lorsqu'un fichier ou un répertoire change
Comment puis-je facilement faire cela?
Utilisez inotify-tools.
[incron] (http://inotify.aiken.cz/?section=incron&page=about&lang=en) est une autre option. –
fanotify est une autre option. Construit sur le dessus d'inotify. Il a quelques améliorations à inotify, par exemple il peut notifier les changements de fichiers dans un répertoire spécifique. –
Ce serait bien si cette réponse incluait l'information pertinente au lieu d'être juste un lien. – Darkhogg
Vérifiez le moniteur système de fichiers du noyau démon
http://freshmeat.net/projects/kfsmd/
Voici un how-to:
Comme mentionné, inotify-tools est probablement la meilleure idée. Cependant, si vous programmez pour le plaisir, vous pouvez essayer de gagner des XPs hacker par une application judicieuse de tail -f.
Il y a aussi [inotail] (http://distanz.ch/inotail/). –
Intéressant, mais comment faites-vous cela? tail -f est une instruction de blocage, nous en avons besoin pour retourner afin de lancer un script? – pdem
@pdem lit sa sortie - toute sortie signifierait que le fichier a changé. Je ne suis pas sûr de ce qu'il fait si le fichier * se rétrécit * si – Xen2050
est ici une autre option: http://fileschanged.sourceforge.net/
Voir en particulier « exemple 4 », qui « surveille un répertoire et les archives des fichiers nouveaux ou modifiés ».
Que diriez-vous de ce script? Utilise la commande 'stat' pour obtenir l'heure d'accès d'un fichier et exécute une commande chaque fois qu'il y a un changement dans le temps d'accès (chaque fois qu'un fichier est accédé).
#!/bin/bash
while true
do
ATIME=`stat -c %Z /path/to/the/file.txt`
if [[ "$ATIME" != "$LTIME" ]]
then
echo "RUN COMMNAD"
LTIME=$ATIME
fi
sleep 5
done
Il vaut mieux utiliser 'inotifywait' (inotify-tools) car il se réveille presque instantanément lorsque le fichier est mis à jour. (Votre script attendrait jusqu'à 5 secondes avant de le remarquer.) Votre script doit également se réveiller toutes les 5 secondes, générer un processus, vérifier le résultat et ensuite se rendormir, alors que ceci est assez bon pour un "hack it together in 5". minutes "-script, cela gaspille les ressources CPU et devrait être évité dans le code de production. – alexander255
-je utiliser ce script pour exécuter un script de compilation sur les changements dans une arborescence de répertoires:
#! /bin/bash
DIRECTORY_TO_OBSERVE="js" // might want to change this
function block_for_change {
inotifywait -r \
-e modify,move,create,delete \
$DIRECTORY_TO_OBSERVE
}
BUILD_SCRIPT=build.sh // might want to change this too
function build {
bash $BUILD_SCRIPT
}
build
while block_for_change; do
build
done
Utilise inotify-tools
. Vérifiez inotifywait
man page pour savoir comment personnaliser ce qui déclenche la construction.
Est-ce que cela n'a pas une condition de concurrence? Si vous modifiez un fichier pendant la construction, il ne l'attrapera pas. – FSMaxB
@FSMaxB oui, c'est le cas. Si je devais enregistrer les modifications pendant la construction, j'enregistrerais à nouveau l'un des fichiers source quand il serait fini pour déclencher une nouvelle construction. –
Juste à des fins de débogage, quand j'écris un script shell et que vous souhaitez l'exécuter sur Enregistrer, j'utilise ceci:
#!/bin/bash
file="$1" # Name of file
command="${*:2}" # Command to run on change (takes rest of line)
t1="$(ls --full-time $file | awk '{ print $7 }')" # Get latest save time
while true
do
t2="$(ls --full-time $file | awk '{ print $7 }')" # Compare to new save time
if [ "$t1" != "$t2" ];then t1="$t2"; $command; fi # If different, run command
sleep 0.5
done
Exécuter comme
run_on_save.sh myfile.sh ./myfile.sh arg1 arg2 arg3
Edit: Au-dessus testé sur Ubuntu 12.04, pour Mac OS, modifiez les lignes ls à:
"$(ls -lT $file | awk '{ print $8 }')"
Ajouter ce qui suit à ~/.bashrc:
function react() {
if [ -z "$1" -o -z "$2" ]; then
echo "Usage: react <[./]file-to-watch> <[./]action> <to> <take>"
elif ! [ -r "$1" ]; then
echo "Can't react to $1, permission denied"
else
TARGET="$1"; shift
ACTION="[email protected]"
while sleep 1; do
ATIME=$(stat -c %Z "$TARGET")
if [[ "$ATIME" != "${LTIME:-}" ]]; then
LTIME=$ATIME
$ACTION
fi
done
fi
}
Vous pouvez essayer l'outil entr
pour exécuter des commandes arbitraires lorsque les fichiers changent. Exemple de fichiers:
$ ls -d * | entr sh -c 'make && make test'
ou:
$ ls *.css *.html | entr reload-browser Firefox
Pour les répertoires utilisent -d
, mais vous avez à l'utiliser dans la boucle, par exemple:
while true; do find path/ | entr -d echo Changed; done
ou:
while true; do ls path/* | entr -pd echo Changed; done
+1. Je pense que c'est sur le sujet (pas sûr pourquoi quelqu'un a voté pour passer au super-utilisateur - cette question est sur shell * programmation *), et une bonne question. –
J'ai un post, je pense est fondamentalement le même: http://stackoverflow.com/q/2972765/119790 –
@ MerlynMorgan-Graham Je déplacerais cela à superutilisateur, parce que la réponse pourrait ne rien avoir à faire avec la programmation - ie il peut y avoir une option de programme ou de configuration qui peut être utilisée, sans aucune programmation nécessaire. J'ai eu la même question, et j'ai d'abord recherché super-utilisateur: p – Benubird