37 votes

Déterminer si le fichier est en cours d'écriture ?

Je dois déployer un processus automatisé (via 1 min cron script) qui recherche des fichiers tar dans un répertoire spécifique. Si un fichier tar est trouvé, il est détarré à l'emplacement approprié, puis le fichier tar est supprimé.

Les fichiers tar sont automatiquement copiés sur ce serveur par SSH depuis un autre serveur. Dans certains cas, les fichiers tar sont extrêmement volumineux, avec beaucoup de fichiers.

Le problème que je m'attends à rencontrer : S'il faut > 1 minute pour que le fichier tar soit copié sur le serveur, et que le cron script s'exécute une fois par minute, il va voir le fichier .tar.gz et essayer de le dé-tarer, même si le fichier tar est toujours en cours d'écriture.

Existe-t-il un moyen (via des commandes bash) de tester si un fichier est en cours d'écriture, ou si ce n'est qu'un fichier partiel, etc ?

Une alternative à laquelle je pensais était de faire en sorte que le fichier soit copié sous une extension de fichier différente (comme par exemple .tar.gz.part ), puis renommé en .tar.gz après que le transfert soit terminé. Mais je me suis dit que j'allais essayer de savoir s'il n'y avait pas simplement un moyen de déterminer si le fichier est entier à la ligne de commande d'abord... Des indices ?

2voto

vogella Points 4884

使用方法 inotifywait peut réaliser ce que vous recherchez - il a la capacité d'attendre la fin de l'écriture d'un fichier avant d'exécuter une commande.

L'exemple suivant surveille continuellement un dossier à la recherche de nouveaux fichiers et exécute la commande dans la boucle lorsque l'écriture du fichier est terminée.

WATCH_DIR=/directory/to/monitor
DEST_DIR=/x/y/z

/usr/bin/inotifywait --recursive --monitor --quiet -e moved_to -e close_write --format '%w%f' "$WATCH_DIR" | while read -r INPUT_FILE; do

mv "$0" "$DEST_DIR"

done

Pour plus d'options de configuration, voir https://linux.die.net/man/1/inotifywatch

0voto

buley Points 7880

J'utilise un script Python qui vérifie la taille de jusqu'à ce qu'elle soit la même sur 2 itérations en temps différent (dans mon cas, avec 0.05s de différence entre les vérifications, le travail est fait !)

    dict={}
    for filename in os.listdir(basepath+'/in'+stage):

        fullInFilename=myfile

        try:
            if not filename in dict:
                #nuevo item...
                time.sleep(0.05)
                dict = {filename: os.stat(fullInFilename).st_size}
                break
            else:  # ya existe en dict, terminó de copiar?
                time.sleep(0.05)
                sizeRegistrado = dict[filename]
                sizeActual = os.stat(fullInFilename).st_size

                if sizeActual != sizeRegistrado:
                    # sigue copiando...
                    dict[filename] = sizeActual
                    print(sizeActual)
                    break
                else:
                    # Terminada
                    #print("pop!")
                    dict.pop(filename)

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X