Je souhaite déplacer un gros fichier créé par un processus externe dès qu'il est fermé.
Cette commande de test est-elle correcte?
if lsof "/file/name"
then
# file is open, don't touch it!
else
if [ 1 -eq $? ]
then
# file is closed
mv /file/name /other/file/name
else
# lsof failed for some other reason
fi
fi
EDIT: le fichier représente un ensemble de données et je dois attendre qu'il soit terminé pour le déplacer afin qu'un autre programme puisse agir dessus. C'est pourquoi j'ai besoin de savoir si le processus externe se fait avec le fichier.
linux
shell-script
monitoring
open-files
lsof
Peter Kovac
la source
la source
lsof
tout besoin de vérifier si l'extension de fichier ne l'est pas.tmp
. Cela le rend trivial. Cependant, je suis content d'avoir posé ma question depuis que j'ai appris un peu surlsof
etinotify
et tout ça.Réponses:
Depuis la
lsof
page de manuelCela suggère donc que votre
lsof failed for some other reason
clause ne sera jamais exécutée.Avez-vous essayé de simplement déplacer le fichier alors que votre processus externe l'a toujours ouvert? Si le répertoire de destination se trouve sur le même système de fichiers, cela ne devrait poser aucun problème, sauf si vous devez y accéder sous le chemin d'origine à partir d'un troisième processus, car l'inode sous-jacent restera le même. Sinon, je pense
mv
qu'il échouera de toute façon.Si vous devez vraiment attendre que votre processus externe soit terminé avec le fichier, il est préférable d'utiliser une commande qui bloque au lieu de l'interrogation répétée. Sous Linux, vous pouvez l'utiliser
inotifywait
pour cela. Par exemple:Si vous devez utiliser
lsof
(peut-être pour la portabilité), vous pouvez essayer quelque chose comme:Mettre à jour
Comme indiqué par @JohnWHSmith ci-dessous, la conception la plus sûre utiliserait toujours une
lsof
boucle comme ci-dessus car il est possible que plus d'un processus ait le fichier ouvert pour l'écriture (un exemple de cas peut être un démon d'indexation mal écrit qui ouvre les fichiers avec la lecture / write flag alors qu'il devrait vraiment être en lecture seule).inotifywait
peut toujours être utilisé à la place du sommeil, remplacez simplement la ligne de sommeil parinotifywait -e close /path/to/file
.la source
inotify
. Malheureusement, il n'est pas installé sur ma boîte mais je suis sûr que je trouverai un paquet quelque part. Voir ma modification pour une raison pour laquelle j'ai besoin que le fichier soit fermé: c'est un ensemble de données et il doit être complet avant de le traiter plus loin.inotifywait
le script ne puisse pas "poller" deux fois souvent, l'OP doit toujours vérifierlsof
dans une boucle: si le fichier est ouvert deux fois, une fermeture pourrait déclencher l'inotify
événement, même si le fichier n'est pas prêt à être manipulé (par exemple, dans votre dernier extrait de code, votresleep
appel pourrait être remplacé parinotifywait
).close_write
devrait être correct car un seul processus peut ouvrir le fichier en écriture à la fois. Il suppose qu'un autre ne l'ouvrira pas immédiatement après sa fermeture, mais le même problème existe avec l'lsof
interrogation.CLOSE_WRITE
est déclenché deux fois).Comme approche alternative, c'est le cas parfait pour un tuyau - le deuxième processus traitera la sortie du premier processus dès qu'il sera disponible, plutôt que d'attendre la fin du processus complet:
Avantages:
Si vous n'avez aucun moyen de créer directement un pipe mais que vous avez des coreutils GNU, vous pouvez utiliser ceci:
Cela commencera à lire le fichier d'entrée depuis le début, quelle que soit la distance parcourue par le premier processus lors de l'écriture du fichier (même s'il n'est pas encore commencé ou déjà terminé).
la source
cat
etprocess2
pourrait terminer avant laprocess1
fin. Ils ne bloqueraient pas.