regarder un file et comparer la sum de contrôle

Essayer d'get un script pour regarder un file et comparer le md5sum du file toutes les 60 secondes, s'il a changé puis imprimer un avertissement à l'écran.

Je ne sais pas comment y aller. C'est ce que j'ai mais je pense que je suis un peu

#/bin/bash watch=$@ if [ -z "$watch" ] then echo "No file specified, aborting" exit else echo "watching : $watch" fi while [ 1 ]; do watch -n 60 -d md5sum $watch done 

Je l'ai aussi fait et cela semble fonctionner (genre de), il me dit si le file a changé mais il n'utilise pas la command watch, y a-t-il un moyen de le faire via une montre?

 #/bin/bash watch=$@ if [ -z "$watch" ] then echo "No file specified, aborting" exit else echo "watching : $watch" fi checksum1="empty" while [ 1 ]; do checksum2=$(md5sum $watch | md5sum | cut -d ' ' -f1) if [ "$checksum2" != "$checksum1" ]; then echo "Warning : $watch has been changed" #mail -s "$watch has been changed" "mikeleahy1234@gmail.com" echo -e "\a" fi checksum1="$checksum2" sleep 60 done 

Essayez ce script approximatif, il s'agit de votre idée de fournir un argument de file et d'utiliser md5sum. Il affiche une ligne avec un horodatage chaque fois que des modifications basées sur md5sum sont différentes, enregistre un file journal et s'arrête lorsque vous ctrl-c. Contenu de watch_and_notify.sh :

 #!/bin/bash logf="$1.log" interval=2 first_run= # temp files, current and last md5s for diff to compare lm1="$(mktemp /tmp/lm1.$$.XXXX)" lm2="$(mktemp /tmp/lm2.$$.XXXX)" if [ -z "$1" ]; then echo "No file specified, aborting" >&2 exit 1 fi echo "Watching at ${interval}s intervals: $1" # loop forever until cancel this script while true; do md5sum "$1" > $lm1 # otherwise in the first iteration, # lm2 does not yet exist, so diff # will always unintentionally report # a difference when comparing existing # file with nonexisting file if [ -z "$first_run" ]; then cp -a $lm1 $lm2 first_run=1 fi # test ! to invert usual exit code if ! diff $lm2 $lm1; then echo -e "$(date +"%F %R")\tChange detected:\t$1" | tee -a "$logf" fi # rotate mv $lm1 $lm2 sleep $interval done # when you ctrl-c it should garbage cleanup trap "rm $lm1 $lm2; exit 1" SIGINT 

Exemple

Démarrer un file text vide nommé a.txt

 $ touch a.txt 

Exécutez le script comme ceci et voyez:

 $ ./watch_and_notify.sh a.txt Watching at 2s intervals: a.txt 

Sur un second terminal, vous testez un changement, par exemple

 $ echo addition >> a.txt 

Sur le premier terminal exécutant le script, vous verrez une mise à jour:

 Watching at 2s intervals: a.txt 1c1 < d41d8cd98f00b204e9800998ecf8427e a.txt --- > 9913e6909c108b5c32c69280474b2b2a a.txt 2015-09-29 15:56 Change detected: a.txt 

Sur le deuxième terminal, vous introduisez à nouveau un autre changement:

 $ echo anotherchange >> a.txt 

Ensuite, sur le premier terminal exécutant le script, la sortie est à nouveau mise à jour:

 Watching at 2s intervals: a.txt 1c1 < d41d8cd98f00b204e9800998ecf8427e a.txt --- > 9913e6909c108b5c32c69280474b2b2a a.txt 2015-09-29 15:56 Change detected: a.txt 1c1 < 9913e6909c108b5c32c69280474b2b2a a.txt --- > 5c1c20a75b9982128f8300a7940f9ce0 a.txt 2015-09-29 16:06 Change detected: a.txt 

Vous quittez avec ctrl-c . et sera returnné à l'invite de command. Vous listz le contenu et voyez qu'il y a un journal:

 $ ls -lh total 12K -rw-r--r-- 1 meme meme 22 Sep 29 16:06 a.txt -rw-r--r-- 1 meme meme 80 Sep 29 16:06 a.txt.log -rwxrwxrwx 1 meme meme 775 Sep 29 15:26 watch_and_notify.sh 

En regardant le journal, vous voyez les mêmes inputs horodatées enregistrant les moments de changement:

 $ cat a.txt.log 2015-09-29 15:56 Change detected: a.txt 2015-09-29 16:06 Change detected: a.txt 

Explication du code

La plupart du stream global peut être compris dans les commentaires du script, mais il exécute à plusieurs resockets une command md5sum sur le file, tout en enregistrant ce résultat et en le faisant tourner pour que le programme diff compare le résultat actuel au résultat de l'itération précédente est une différence, puis effectuez l'action de génération de rapports. Dans ce cas, ces actions doivent être affichées à l'écran avec horodatage ainsi que pour append à un journal. L'user arrête le script avec ctrl-c, et est laissé avec un journal des moments horodatés lorsque des différences ont été détectées.

Dans le script

 lm1="$(mktemp /tmp/lm1.$$.XXXX)" lm2="$(mktemp /tmp/lm2.$$.XXXX)" 
  • lm1 et lm2 sont des files temporaires pour stocker les sorties de md5sum à des fins de comparaison, générées uniquement lorsque notre script est exécuté
  • l'approche key est comme vous l'avez dit, en comparant littéralement md5sums, afin de faire que nous définissions d'abord un endroit temporaire pour les stocker
  • mktemp pour aider à créer un nom de file temporaire unique.
  • $$ est l'identifiant du process en cours, pour lancer un peu d'random
  • XXXXX indique à mktemp de replace chaque X par des caractères alphanumériques randoms

Ainsi, lors de l'exécution, nous pouvons vérifier et voir / tmp en effet contenir au less un file nommé avec notre model défini:

 $ ls -lh /tmp/lm* -rw-r--r-- 1 meme meme 40 Sep 29 15:08 /tmp/lm2.8248.xGJTl 

Ensuite, nous avons la boucle while:

 # loop forever until cancel this script while true; do ... done 

La majorité du code est prise en sandwich dans un grand while <command>; do ... done while <command>; do ... done boucle while <command>; do ... done . Comme la command / condition est true et sera toujours, ce code s'exécute indéfiniment jusqu'à ce que nous ctrl-c .

Chaque itération de boucle commence par générer les résultats md5sum de l'itération en cours et en l'enregistrant:

 md5sum "$1" > $lm1 
  • $1 signifie le premier argument positionnel. Dans ce cas, lors de l'exécution de watch_and_notify.sh a.txt , $1 sera un a.txt
  • > $lm1 pour écrire la sortie dans notre file temporaire défini précédemment

Lors de la première exécution, il n'y aura pas d'itération précédente. Pourtant, la façon dont la command diff est arrangée, il doit comparer les changements du résultat md5sum précédent $lm2 à $lm1 , qui, lors de la première exécution, montreront toujours involontairement une différence, de sorte que lors de la première exécution, il fallait une action conditionnelle spéciale . Pour pouvoir reconnaître la première exécution, nous faisons une variable vide initiale, définie avant la boucle while:

 first_run= 

Ensuite, dans la boucle, nous testons ceci:

  if [ -z "$first_run" ]; then cp -a $lm1 $lm2 first_run=1 fi 
  • -z teste pour la valeur zéro. Si c'est la première itération, $ first_run est toujours vide, continue donc la partie then
  • dans la partie then , nous "simulons" une "itération précédente" en faisant un doublon de $lm1 , donc plus tard sur diff , pour la première itération, nous comparons deux files identiques et ne rapportons pas de différence.
  • first_run=1 sorte que la prochaine itération if [ -z "$first_run" ]; then if [ -z "$first_run" ]; then $first_run ne sera plus nulle, donc la partie then ne sera pas déclenchée, assurant ainsi que cette action n'est prise que pour la première itération

Ensuite, nous avons la condition diff actuelle, qui compare les résultats md5sum de l'itération précédente, enregistrés dans le file référencé dans la variable $lm2 , par rapport aux résultats md5sum de l'itération en cours, enregistrés dans le file référencé dans $lm1

 if ! diff $lm2 $lm1; then 
  • nous comptons sur la réaction aux codes de sortie de la command diff
  • normalement diff file1 file2 donne le code de sortie 0 quand ils sont identiques. vous pouvez tester ceci quand vous exécutez $ diff a.txt a.txt; echo $? $ diff a.txt a.txt; echo $? , vous voyez un zéro. Quand différent par exemple $ diff a.txt b.txt; echo $? $ diff a.txt b.txt; echo $? tant que b.txt est différent, il y aura un résultat 1
  • mais 0 est reconnu par bash comme étant true et 1 signifie false
  • donc nous ne pouvons pas faire if diff $lm2 $lm1; then if diff $lm2 $lm1; then parce que diff quand les files sont identiques, donnerait le code de sortie 0, interprété comme true , et triggersrait la partie then
  • nous voulons le comportement opposé, si identique ne rien faire, sinon identique faire quelque chose
  • ! aide à inverser la sortie

Nous pouvons donc tester un changement,

En cas de changement, les mesures sockets sont les suivantes:

  echo -e "$(date +"%F %R")\tChange detected:\t$1" | tee -a "$logf" 
  • echo avec -e pour rendre \t comme des tabulations
  • date +"%F %R" pour rendre l'horodatage actuel dans le format donné, par exemple 2015-09-29 15:56
  • | pour diriger la sortie vers le programme tee
  • tee nous permet de voir le message de sortie à propos d'un changement, ainsi que de sauvegarder la sortie
  • -a définit le mode d'logging à append, sinon, à chaque fois qu'il y a des résultats, il écraserait les résultats précédents

Nous avons presque terminé les tâches de cette itération actuelle. Après avoir terminé la comparaison et les actions diff , nous faisons cela pour préparer la prochaine itération:

  mv $lm1 $lm2 
  • mv pour déplacer / renommer le résultat md5sum de l'itération courante enregistré à $lm1 , à $lm2 .
  • donc prochaine itération de diff $lm2 $lm1 il sera en effet de comparer le md5sum de l'itération précédente

Enfin, la dernière ligne de la boucle est la clause sleep sleep $ interval

  • sleep pour provoquer un retard, en secondes, donné par $interval variable d' $interval
  • $interval variable d' $interval définie au début du file à 2
  • ainsi chaque itération durera 2 secondes

    terminé

  • Finalement, il y a un done pour fermer le while ...;do ... done boucle

Je déteste que ce soit la réponse, mais après environ 15 minutes de jeu avec cela, je ne pense pas qu'il y ait un moyen d'y arriver avec la command de la watch (bien que quelqu'un d'autre, s'il vous plaît me prouver le contraire)

Le problème réside dans le fait que la watch elle-même fonctionne dans sa propre boucle et ne se casse pas pour fournir des données au shell, elle fournit seulement son propre écho.

En raison de la façon dont fonctionne la watch , l'utiliser à l'intérieur de n'importe quel type de requête if ou while ne permet pas au shell d'évaluer les modifications apscopes, car il ne rend jamais ses résultats. Il tient simplement sur eux jusqu'à ce que vous sortiez c'est boucle manuellement.

Exécuter votre propre boucle et vérifier le md5sum de la façon dont vous êtes dans votre deuxième exemple est sur la meilleure façon d'accomplir ce que vous cherchez à faire.

Par exemple, problème

 echo `watch -d md5sum testfile.txt` 

l'écho ne s'éteindra jamais. Si vous pouvez find un moyen de faire que cet écho frappe le terminal, c'est la réponse à votre script.

Vous êtes beaucoup mieux avec inotify , ce qui est fait pour ce genre de but: la surveillance des files.


EDIT : Je vais résumer les réponses de la question liée ici.

Chaque fois que vous avez besoin de surveiller un file ou un directory, inotify est le bon outil pour le travail. Vous pouvez indiquer inotifywait les events que vous souhaitez surveiller: access aux files, modification, ouverture, fermeture, suppression … (Voir man inotifywait pour plus de détails).

Une première approche est une boucle comme celle-ci:

while inotifywait -e close_write myfile.py; do ./myfile.py; done

L'inconvénient majeur est que vous pourriez manquer des events. Une version plus efficace serait:

 inotifywait -mq --format '%e' /path/to/file | while IFS= read -r events; do /path/to/script "$events" done 

Cette dernière version ne manquera pas un seul événement. Le tube garantit que les events sont mis en queue. Si la boucle ne les choisit pas en time opportun, ils vont s'accumuler mais aucun ne sera manqué.


EDIT : Si vous traquez des files text, je reorderais aussi git car il traque les files en utilisant des hachages robustes. Voici un pseudo-code bash pour savoir à quoi ressemblerait la principale boucle inotify :

 git status file # Tells whether <file> was modified if file was modified; then git commit -- file # Add <file> to the repository keep only the last two versions of <file> print the warning message fi 

Vous pouvez l'utiliser comme base. Vous devrez peut-être parsingr la sortie git . Je ne l'ai pas utilisé assez intensément pour vous dire comment exactement, mais j'ai l'printing qu'il peut le faire ;-).