7
votes

Comment attendre que le fichier soit fermé

J'ai un processus externe qui commence à écrire dans un fichier.
Comment écrivez-moi un script qui attend que le fichier soit fermé (lorsque l'autre processus effectué avec l'écriture).


0 commentaires

5 Réponses :


2
votes

Le moyen facile: laissez le script exécuter le programme et attendre que ce soit fini.


0 commentaires

1
votes

Ce n'est pas agréable, et ça me fait me sentir sale l'écrire ... /tmp/foo.txt est le fichier testé ...

#!/bin/bash

until [ "$( find /proc/*/fd 2> /dev/null | 
   xargs -i{} readlink {} |
   grep -c '^/tmp/foo.txt$' )" == "0" ]; do

   sleep 1;
done;


0 commentaires

2
votes

Il y a plusieurs façons d'y parvenir:

  • Si vous le pouvez, démarrez le processus à partir de votre script. Le script se poursuivra lorsque le processus se termine et cela signifie qu'il ne peut plus écrire de données dans le fichier.

  • Si vous ne pouvez pas contrôler le processus, vous savez que le processus se termine après avoir rédigé le fichier, vous pouvez trouver l'ID de processus, puis vérifier si le processus est toujours en cours d'exécution avec kill -0 $ PID . Si $? est 0 par la suite, le processus est toujours en vie.

  • Si ce n'est pas possible, vous pouvez utiliser lsof -np $ pid pour obtenir une liste de tous les fichiers ouverts pour ce processus et vérifier si votre fichier est dans la liste. C'est quelque peu lent, cependant.

    [modifier] Notez que toutes ces approches sont quelque peu fragiles. La solution correcte consiste à avoir le processus externe écrire le fichier à l'aide d'un nom temporaire, puis renommez-le dès que cela sera fait.

    La renommée s'assure que tout le monde voit tout le fichier avec toutes les données ou rien.


7 commentaires

Que diriez-vous de ! lsof - / chemin / à / à / fichier ?


@RubyTuesdaydono: qu'en est-il?


Je suggérant qu'il s'agissait d'une manière plus directe d'interroger si tout processus a ce fichier spécifique ouvert (versus grep à travers une liste de tous les fichiers ouverts par le processus le plus probable). Votre recommandation secondaire autour de renommer des fichiers temporaires en place une fois que vous êtes terminé, semble être une option supérieure - je veux juste mettre en évidence que lsof est une commande sophistiquée avec plusieurs vecteurs pour acclamer exactement les informations souhaitées.


@RubyTuesdaydono: ah. Je suggère de toujours spécifier l'option -n pour utiliser des cas comme celui-ci, donc lsof ne passe pas beaucoup de temps à faire des recherches DNS.


Je n'ai observi aucune recherche DNS sur mon VPS Fedora (OpenVz) lors de l'utilisation de Strace avec un argument de nom de fichier (par exemple, Cat >> File & Strace -F -E Trace = réseau LSOF - - Fichier ) - Bien que je conviens que c'est une bonne habitude d'être explicite dans la mesure du possible, car les implémentations peuvent varier sauvagement:]


Le comportement ne dépend pas de lsof mais sur le processus que lsof analyses. Exécutez-le sur un serveur Web occupé et il peut prendre une demi-heure pour résoudre toutes les adresses clientes.


Ah, à droite ... surtout depuis d'autres processus (en plus de celui que nous prévoyons) pourrait avoir le fichier cible ouverte.



0
votes

LOOP jusqu'à ce que le fichier soit une approche stable, cela devrait fonctionner si vous attendez des résultats expérimentations (vous n'avez donc pas besoin de manipulation d'événements en temps réel):

EXPECTED_WRITE_INTERVAL_SECONDS=1
FILE="file.txt"
while : ; do
        omod=$(stat -c %Y $FILE)
        #  echo "OLD: $omod"
        sleep $EXPECTED_WRITE_INTERVAL_SECONDS
        nmod=$(stat -c %Y $FILE)
        #  echo "NEW: $nmod"
        if [ $omod == $nmod ] ; then
                break
        fi
done


0 commentaires

2
votes

Créer un petit programme C à l'aide de inotify . Le programme devrait:

  1. créer un inotify instance.
  2. Ajoutez une montre à l'instance pour le in_close_write Evénement pour le chemin du fichier d'intérêt.
  3. Attendez l'événement.
  4. Sortie avec un code approprié.

    Puis dans votre script, appelez le programme avec le chemin de fichier comme argument.

    Vous pouvez l'étendre en ajoutant un argument de délai d'attente et permettant de spécifier différents événements.


0 commentaires