/ Conditions de course pour la création de fichiers Linux / Linux - linux, find, timestamp

Conditions de course d'horodatage de création de fichiers Linux - linux, find, horodatage

J'essaie de faire ce que je pense est une chose simplesous Linux. J'ai un script bash qui exécute divers programmes de test et je souhaite déterminer quels fichiers du répertoire actuel ont été créés par les programmes de test. Donc, je fais quelque chose comme ça:

Appuyez sur timestamp-file faire le test find -newer timestamp-file -type f> liste de fichiers rm -f fichier_horodatage

Il se trouve que la granularité de find -newer est médiocre. Par conséquent, certains fichiers générés par le programme de test sont plus anciens que le fichier d'horodatage. Alors j'ai essayé ceci:

ls -tr1 | sed "1, / fichier timestamp / d"

générer la même liste. Ce d'habitude fonctionne, mais pas toujours. Je me retrouve toujours dans la situation où les fichiers générés par le test sont plus anciens que le fichier d'horodatage.

Merci!

P.S. Je peux accomplir cela d'une autre manière en prenant deux instantanés du répertoire, un avant l'exécution du programme de test, puis un après, et en les comparant. Tous les fichiers de la seconde liste qui ne figurent pas dans la première doivent avoir été créés par le programme de test (je ne suis pas concerné par les jobs d’arrière-plan ou les autres utilisateurs écrivant dans le répertoire). Mais cette méthode n’est pas ce que je veux car si une sortie le fichier n'a pas été supprimé avant l'exécution du test (ils sont supposés l'être, mais dans certains cas, ils ne le sont pas), cette méthode dira qu'il n'a pas été créé par le programme de test car il était dans le répertoire avant le programme de test Était dirigé.

Réponses:

1 pour la réponse № 1

Prenez les noms de fichiers de tous les fichiers avant la course, mais incluez leur horodatage:

find -printf "%p %T@n" | sort > file1

Si cette option de recherche n’est pas disponible, vous pouvez également utiliser stat pour cet emploi:

find -print0 | xargs -0 stat -c "%n %Y" | sort > file1

</ sub>

Et après la course à file2. Puis utiliser

comm -1 -3 file1 file2

Et il vous montrera les lignes uniques à file2, qui doivent être de nouveaux fichiers si je ne me trompe pas. S'ils existaient auparavant, leur heure de modification aura changé, ce qui est pris en charge par le %T@ thingy (indiquant le nombre de secondes depuis 1970):

[js @ HOST2 cpp] $ find -printf "% p% T @ n" | trier>fichier1 [js @ HOST2 cpp] $ echo foo> bar [js @ HOST2 cpp] $ echo foo> baz [js @ HOST2 cpp] $ find -printf "% p% T @ n" | trier> fichier2 [js @ HOST2 cpp] $ comm -1 -3 fichier1 fichier2 . 1230947309.0000000000 ./bar 1230947308.0000000000 ./baz 1230947309.0000000000 ./fichier2 1230947315.0000000000 [js @ HOST2 cpp] $ find -printf "% p% T @ n" | trier> fichier1 [js @ HOST2 cpp] $ echo lol> bar [js @ HOST2 cpp] $ find -printf "% p% T @ n" | trier> fichier2 [js @ HOST2 cpp] $ comm -1 -3 fichier1 fichier2 ./bar 1230947359.0000000000 ./fichier2 1230947362.0000000000 [js @ HOST2 cpp] $ `

3 pour la réponse № 2

Vous pouvez réellement utiliser touch pour forcer l'horodatage de tous les fichiers actuels du répertoire, comme par exemple:

touch -t 200801010000.00 *

Si vous faites cela avant d'exécuter votre test, il devrait y avoir une différence plus que suffisante dans le temps "find -newer"pour le ramasser. Si la granularité était de deux minutes, vous pouvez définir tous les fichiers actuels sur il y a dix minutes, le fichier d'horodatage sur il y a 5 minutes, puis exécuter votre test.

Donc, votre script devient:

touch -t (current time - 10 minutes) *
touch -t (current time -  5 minutes) timestamp-file
run the test
find -newer timestamp-file -type f > list-of-files
rm -f timestamp-file

En supposant que vous ayez une installation décente de Perl, vous pouvez procéder comme suit pour obtenir il y a 5 minutes (ou utiliser -600 pendant 10 minutes) au format correct "date -t":

use Date::Manip;
print UnixDate(DateCalc(ParseDateString("now"),"-300"),"%Y%m%d%H%M.%S") . "n";

Si, pour une raison quelconque, vous n'êtes pas autorisé à modifier les horodatages, utilisez:

sleep 300
touch timestamp-file
sleep 300
run the test
find -newer timestamp-file -type f > list-of-files
rm -f timestamp-file

ce qui a le même effet, mais vous donne dix minutes pour aller prendre un café (ou votre poison de choix si vous n'êtes pas un buveur de café).


2 pour la réponse № 3

Si vous considérez comment find(1) est mis en œuvre, il sera clair pourquoi cela peut parfois ne pas fonctionner comme prévu. Voici un indice:

  $ touch timestamp ; touch newer ; find . -newer timestamp
$ rm timestamp newer
$ touch timestamp ; sleep 1 ; touch newer ; find . -newer timestamp
.
./newer
$

find(1) obtient les valeurs du fichier mtime / ctime / atime à l'aide de l'appel système stat(2). Voici les éléments de struct stat de <sys/stat.h> (Linux):

  time_t    st_atime;   /* time of last access */
time_t    st_mtime;   /* time of last modification */
time_t    st_ctime;   /* time of last status change */

Sous Linux (et les unices en général) time_t est un entier représentant "secondes à partir du début de 1970". Par conséquent, la plus belle granualité qui -newer peut comprendre est juste une seconde.


0 pour la réponse № 4

Pourquoi ne pas créer un répertoire temporaire dans lequelexécuter les tests? Utilisez un nom basé sur un horodatage sur le répertoire pour vous aider à garder une trace des résultats qui se sont produits quand, et supprimez simplement le répertoire entier lorsque vous avez terminé.