2010-04-06 12 views
0

Modifier - Reformulé la question un peu le 7 avril pour la rendre plus claire.SH/BASH - Numérise un fichier journal jusqu'à ce que du texte apparaisse, puis quitte. Comment?

L'environnement de travail actuel est OSX 10.4.11.

Je souhaite analyser un fichier journal pour une phrase donnée. Le fichier journal ne peut PAS être vidé au début du script. Ainsi, le script doit uniquement analyser les modifications apportées au journal.

Mon script actuel:

#!/bin/sh 
    tail -f log.txt | while read line 
do 
    if echo $line | grep -q 'LOL CANDY'; then 
    echo 'LOL MATCH FOUND' 
    exit 0 
    fi 
done 

Il fonctionne correctement dans le fait qu'il « LOL MATCH TROUVÉ » immédiatement après avoir trouvé « LOL CANDY », mais il ne quitte effectivement le script jusqu'à ce qu'il ya une autre ajout au journal APRÈS le «LOL CANDY». J'en ai besoin pour cesser immédiatement. Et même si je ne suis pas sûr que ce soit spécifiquement lié, il y a le problème du "tail -f" qui reste ouvert pour toujours. Quelqu'un peut-il s'il vous plaît me donner un exemple qui fonctionnera sans utiliser tail -f?

Si vous voulez, vous pouvez me donner un script bash, car OSX peut gérer sh, bash et d'autres shells je pense.

Répondre

0
tail -f log.txt | sed -n '/interesting/{ 
p 
q 
}' 

Fondamentalement, lisez les lignes sans rien imprimer; quand vous voyez quelque chose d'intéressant, imprimez la ligne et quittez.

Oh, je vois que vous ne voulez pas de 'queue -f'; c'est étrange, il devrait quitter quand il a besoin d'écrire dans le tuyau. S'il n'écrit plus jamais sur le tuyau, cela pourrait poser problème.

Je suppose que vous pourriez faire:

tail -f log.txt | sed -n '/interesting/{ 
p 
q 
}' 
echo "EOF" >> log.txt 

qui lui donne quelque chose à faire écho, il essaie et échoue et se termine.

+0

"il ne devrait plus écrire dans le tube, il pourrait être un problème" Oui, cela semble être le problème alors. Cependant, votre solution "EOF" ne résout pas le problème; le programme se comporte exactement de la même manière. Peut-être parce que l'EOF est en train d'être ajouté à la fin d'une ligne déjà lue? Je voudrais aller de l'avant et résoudre ce problème moi-même, mais je ne sais pas comment faire écho à une nouvelle ligne. – James

+0

Je pense que 'bash' fait un travail légèrement différent de la façon dont Bourne ou Korn l'utilisaient. J'avais une configuration modestement complexe, mais il est apparu que le shell ne recommencerait pas jusqu'à ce que les deux extrémités du pipeline soient sorties - ou peut-être que l'élément principal ('tail -f') soit obligé de sortir. Classiquement, le statut de sortie d'un pipeline est le statut de sortie de la dernière commande, et quand il se termine, le pipeline est terminé. J'ai rencontré d'autres problèmes avec bash (un code qui fonctionnait bien pendant des années sous des obus non bash) dans des domaines faiblement apparentés - et je n'ai pas compris ce qui se passait. Ennuyeux! –

2

Est-ce que vous effacez log.txt lorsque vous lancez votre script la deuxième fois? Vous pouvez interpréter que cela prend deux apparences de votre ligne de démission, alors qu'en réalité elle n'en prend qu'une. Parce que vous utilisez -f, il ne listera que tout ajouté une fois que vous avez démarré votre script.

Ainsi, la première fois que vous l'attrapez, vous obtenez votre ligne désirée et vous quittez. Vous relancez le script, il ignorera la première instance car il ne sera pas entré dans votre argument -f à queue. Cependant, la prochaine occurrence devrait quitter. Si vous regardez dans votre journal, vous verrez deux lignes LOL CANDY parce que vous suivez juste la queue et ne regardez pas ce qui est déjà dans le journal.

Si vous vouliez que votre script meure à chaque fois que cette ligne apparaît dans le journal, vous pouvez l'ajouter au début de votre script.

#!/bin/sh 
    if grep 'LOL CANDY' log.txt; then 
    echo 'LOL MATCH FOUND' 
    exit 0 
    fi 

    tail -f log.txt | while read line 
do 
    if echo $line | grep -q 'LOL CANDY'; then 
    echo 'LOL MATCH FOUND' 
    exit 0 
    fi 
done 

Aussi, si vous vouliez vous débarrasser de la queue -f, vous pouvez faire ce que j'ai énuméré en premier lieu dans une infinie while (syntaxe peut-être tort, été un certain temps):

#!/bin/sh 
while (1) 
do 
    if grep 'LOL CANDY' log.txt; then 
    echo 'LOL MATCH FOUND' 
    exit 0 
    fi 
done 

Bien sûr, si votre fichier journal devient très volumineux, cela va prendre beaucoup de ressources et prendre beaucoup de temps.

+0

Le journal ne sera pas effacé chaque fois, il n'est pas possible de le faire. Je m'excuse de ne pas l'avoir dit dans la question initiale et, autant que je sache, cela nie toutes vos solutions proposées. – James

0

essayer cette

(tail -f file| awk '/interesting/{print;exit}') 
+0

J'ai essayé cela; il fonctionne identique au mien. En d'autres termes, il doit y avoir une entrée supplémentaire dans le journal APRÈS la phrase-clé pour que le script se termine réellement. Des idées? – James

0

Je ne suis pas tout à fait sûr si je comprends bien votre question. Quoi qu'il en soit, j'ai essayé votre script, il ne s'est pas arrêté en première partie. Alors, diriez-vous d'ajouter:

pid=`ps -ef | grep "tail -f log.txt" | grep -v grep | awk '{print $2}'` 
kill -2 $pid 

avant exit 0 de sorte que les sorties tail -f?

+0

C'est ce qui se passe lorsque j'essaie ce code: ps: option illégale - f utilisation: ps [-aACcehjlmMrSTuvwx] [-O | o fmt] [-p pid] [-t tty] [-U utilisateur] ps [-L] kill: utilisation: kill [-s sigspec | -n signum | -sigspec] [pid | travail] ... ou kill -l [sigspec] se déconnecter [Processus terminé] – James

+0

Il ne semble pas y avoir une option -f dans le ps OSX je suppose. – James

+0

@James c'est intéressant. J'ai essayé l'extrait sur mon macbook pro, avec la dernière version de léopard des neiges. Ça s'est bien passé! En outre, jetez un oeil à la page de manuel en ligne pour OS X http://developer.apple.com/mac/library/DOCUMENTATION/Darwin/Reference/ManPages/man1/ps.1.html, il a -f option quoi version courez-vous? –

1

Peut-être que ce script vous aidera à:

#!/bin/bash 

FILE=/tmp/mytest 
PIPE=/tmp/myfifo 

if [[ ! -p $PIPE ]]; 
then 
     mkfifo $PIPE 
fi 

tail -n 0 -f $FILE >> $PIPE & 
TAILPID=$! 

while read line < $PIPE 
do 
     echo "Received: $line" 
     if [ "x$(echo "$line" | grep -l -P "asdf")" != "x" ]; 
     then 
       echo "MATCHES" 
       kill -TERM $TAILPID 
     fi 
done; 
0

Je cherchais cela, et compris les travaux suivants (pour ma demande de toute façon):

tail -n 1 -f /var/log/vmkernel.log | grep -m 1 IOMMUIntel >>/var/log/vmkernel.log 

Tails le journal, grep découvertes le texte, et grep écrit le texte dans le journal, ce qui tue le tail et je suis de retour à l'invite. En particulier, il teste lorsqu'une carte vidéo transmise devient active lors du démarrage d'une machine virtuelle sur VMware ESXi.

Le projet complet est here.