2008-12-04 20 views
0

J'essaye d'écrire un script (sh -bourne shell) qui traite les lignes telles qu'elles sont écrites dans un fichier. Je tente de le faire en alimentant la sortie de tail -f dans une boucle while read. Cette tactique semble être fondée sur mes recherches dans Google ainsi que this question traitant d'un problème similaire, mais en utilisant bash. D'après ce que j'ai lu, il semble que je devrais pouvoir sortir de la boucle lorsque le fichier suivi cesse d'exister. Ce n'est pas le cas. En fait, il semble que la seule façon de m'en sortir est de tuer le processus dans une autre session. tail ne semble fonctionner très bien autrement que les essais avec ceci:Décompression de "tail -f" qui est lu par une boucle "while while" dans HP-UX

 
touch file 
tail -f file | while read line 
do 
    echo $line 
done 

données J'ajouter à file dans une autre session apparaît fichier juste du traitement de la boucle écrite ci-dessus.

Il s'agit de la version B.11.23 de HP-UX.

Merci pour toute aide/aperçu que vous pouvez fournir!

Répondre

0

Je ne sais pas sur HP-UX tail mais GNU tail a l'option --follow=name qui suivra le fichier par son nom (en rouvrant le fichier toutes les quelques secondes au lieu de lire à partir du même descripteur de fichier qui ne détecte pas si le fichier est dissociées) et se terminera lorsque le nom de fichier utilisé pour ouvrir le fichier est dissociées:

tail --follow=name test.txt 
+0

Bonjour Robert. J'ai vu cette option dans mes recherches Google, et cela semblait être la meilleure option. Malheureusement, HP-UX ne prend pas en charge cette option. – AgentConundrum

+0

@Agent - Pouvez-vous télécharger et compiler (port) GNU tail? Cela semble certainement être ce que vous voulez. – tvanfosson

+0

@tvanfosson - Il s'agit en quelque sorte d'un projet amusant pour émuler un bon nombre de fonctionnalités du système (MPE) que nous venons de porter. C'est juste pour rendre la vie des développeurs un peu plus facile. Je doute que je puisse obtenir l'approbation pour compiler la queue GNU en dev, sans parler de la production (serait un outil utile pour le travail oncall) – AgentConundrum

1

Si vous voulez sortir, lorsque votre fichier n'existe pas de plus, il suffit de faire:

test -f file || break 

Placin g dans votre boucle, devrait éclater.

Le problème restant est, comment casser la ligne de lecture, car cela bloque.

Cela pourrait vous faire en appliquant un délai d'attente, comme lire -t 5 lignes. Puis, toutes les 5 secondes, la lecture revient, et au cas où le fichier n'existe plus, la boucle se brise. Attention: Créez votre boucle qui peut gérer le cas, que la lecture expire, mais le fichier est toujours présent.

EDIT: Semble que, avec délai d'attente lu renvoie false, vous pouvez donc combiner le test avec le délai d'attente, le résultat serait:

tail -f test.file | while read -t 3 line || test -f test.file; do 
      some stuff with $line 
    done 
+0

Cela continuera à traiter la ligne la plus récente toutes les 3 secondes si aucune nouvelle donnée n'est ajoutée au fichier. –

+0

Cest pourquoi j'ai écrit: "Attention: Créez votre boucle qui peut gérer le cas, que la lecture expire, mais le fichier est toujours présent." – flolo

+0

Cette phrase est très vague et ne rend pas le problème avec cette solution claire. –

0

À moins que vous utilisez GNU queue, il n'y a aucun moyen il se terminera de lui-même en suivant un fichier. L'option -f n'est vraiment destinée qu'à la surveillance interactive - en effet, j'ai un livre qui dit que -f "ne sera probablement pas utile dans les scripts shell". Mais pour une solution au problème, je ne suis pas tout à fait sûr que ce n'est pas une manière trop sophistiquée de le faire, mais je pensais que vous pouviez envoyer le queue à un FIFO, puis avoir une fonction ou script qui vérifiait l'existence du fichier et supprimait la queue si elle n'était pas liée.

 
#!/bin/sh 

sentinel() 
{ 
    while true 
    do 
     if [ ! -e $1 ] 
     then 
      kill $2 
      rm /tmp/$1 
      break 
     fi 
    done 
}  

touch $1 

mkfifo /tmp/$1 

tail -f $1 >/tmp/$1 & 

sentinel $1 $! & 

cat /tmp/$1 | while read line 
do 
    echo $line 
done 

fait quelques tests naïfs, et il semble travailler bien, et ne pas laisser traîner des ordures.

0

Je ne suis jamais satisfait de cette réponse, mais je ne l'ai pas trouvé une alternative: soit

kill $(ps -o pid,cmd --no-headers --ppid $$ | grep tail | awk '{print $1}') 

Obtenir tous les processus qui sont les enfants du processus en cours, recherchez la queue, imprimer la première colonne (pid de la queue), et tuez-le. Sin-freaking-laid en effet, telle est la vie.

0

Les arrière-plans d'approche suivant la commande tail -f file, echos son identifiant de processus plus un préfixe de chaîne personnalisée (ici tailpid:) à la boucle while où la ligne avec le préfixe de chaîne personnalisée déclenche une autre (backgrounded) boucle while que tous les 5 contrôles secondes si file existe toujours. Si ce n'est pas le cas, tail -f file est tué et le sous-shell contenant la boucle while en arrière-plan quitte.

# cf. "The Heirloom Bourne Shell", 
# http://heirloom.sourceforge.net/sh.html, 
# http://sourceforge.net/projects/heirloom/files/heirloom-sh/ and 
# http://freecode.com/projects/bournesh 

/usr/local/bin/bournesh -c ' 
touch file 
(tail -f file & echo "tailpid: ${!}") | while IFS="" read -r line 
do 
    case "$line" in 
     tailpid:*) while sleep 5; do 
         #echo hello; 
         if [ ! -f file ]; then 
          IFS=" "; set -- ${line} 
          kill -HUP "$2" 
          exit 
         fi 
       done & 
       continue ;; 
    esac 
    echo "$line" 
done 
echo exiting ... 
'