44 votes

"regarder" la sortie d'une commande jusqu'à ce qu'une chaîne particulière soit observée, puis quitter

Je cherche un moyen de surveiller de manière programmatique la sortie d'une commande jusqu'à ce qu'une chaîne particulière soit observée, puis de quitter. C'est très similaire à cette question, mais au lieu de suivre un fichier, je veux 'suivre' une commande.

Quelque chose comme:

watch -n1 my_cmd | grep -m 1 "Chaîne que je cherche"

(Mais cela ne fonctionne pas pour moi.)

MISE À JOUR: Je tiens à préciser que 'my_cmd' ne produit pas de texte en continu mais doit être appelé de manière répétée jusqu'à ce que la chaîne soit trouvée (c'est pourquoi j'ai pensé à la commande 'watch'). À cet égard, 'my_cmd' est comme beaucoup d'autres commandes Unix telles que : ps, ls, lsof, last, etc.

50voto

choroba Points 17339

Utilisez une boucle :

jusqu'à ce que ma_cmd | grep -m 1 "String Je Recherche"; faire : ; fin

Au lieu de :, vous pouvez utiliser sleep 1 (ou 0.2) pour soulager le CPU.

La boucle s'exécute jusqu'à ce que grep trouve la chaîne dans la sortie de la commande. -m 1 signifie "une correspondance suffit", c'est-à-dire que grep arrête de chercher après avoir trouvé la première correspondance.

Vous pouvez aussi utiliser grep -q qui arrête également après avoir trouvé la première correspondance, mais sans afficher la ligne correspondante.

13voto

math Points 2507
veiller -e "! ma_cmd | grep -m 1 'Chaîne que Je Recherche'"
  • ! nie le code de sortie du pipeline de commandes
  • grep -m 1 sort quand la chaîne est trouvée
  • veiller -e retourne s'il y a eu une erreur

Mais cela peut être amélioré pour afficher réellement la ligne correspondante, qui est jusqu'à présent ignorée.

10voto

Charles Uy Points 1

Pour ceux qui ont un programme qui écrit continuellement sur stdout, tout ce que vous avez à faire est de le rediriger vers grep avec l'option 'correspondance unique'. Une fois que grep trouve la chaîne correspondante, il se fermera, ce qui fermera stdout sur le processus qui est redirigé vers grep. Cet événement devrait naturellement provoquer la sortie gracieuse du programme tant que le processus écrit à nouveau.

Ce qui se passera, c'est que le processus recevra un SIGPIPE lorsqu'il tentera d'écrire sur stdout fermé après que grep ait quitté. Voici un exemple avec ping, qui autrement s'exécuterait indéfiniment :

$ ping superuser.com | grep -m 1 "icmp_seq"

Cette commande correspondra au premier 'pong' réussi, puis sortira la fois suivante où ping tentera d'écrire sur stdout.


Cependant,

Il n'est pas toujours garanti que le processus écrira à nouveau sur stdout et pourrait donc ne pas provoquer l'élévation d'un SIGPIPE (par exemple, cela peut se produire lors du suivi d'un fichier journal). La meilleure solution que j'ai réussi à trouver pour ce scénario consiste à écrire dans un fichier ; veuillez commenter si vous pensez pouvoir améliorer :

$ { tail -f log_file & echo $! > pid; } | { grep -m1 "find_me" && kill -9 $(cat pid) && rm pid; }

En décomposant cela :

  1. tail -f log_file & echo $! > pid - lit un fichier, attache le processus à l'arrière-plan, et enregistre le PID ($!) dans un fichier. J'ai essayé d'exporter le PID dans une variable, mais il semble qu'il y ait une condition de concurrence entre ici et quand le PID est réutilisé.
  2. { ... ;} - regrouper ces commandes ensemble pour pouvoir rediriger la sortie vers grep tout en conservant le contexte actuel (aide lors de l'enregistrement et la réutilisation des variables, mais je n'ai pas pu faire fonctionner cette partie)
  3. | - rediriger la sortie stdout du côté gauche vers l'entrée stdin du côté droit
  4. grep -m1 "find_me" - trouver la chaîne cible
  5. && kill -9 $(cat pid) - forcer la terminaison (SIGKILL) du processus tail après que grep ait trouvé la chaîne correspondante et quitté
  6. && rm pid - supprimer le fichier que nous avons créé

0voto

Keith Thompson Points 4865
my_cmd | tail +1f | sed '/Chaîne que je recherche/q'

Si tail ne prend pas en charge la syntaxe +1f, essayez tail -f -n +1. (Le -n +1 lui indique de commencer au début; tail -f démarre par défaut avec les 10 dernières lignes de sortie.)

0voto

Sargunan Points 39

Ajoutez le résultat de vos appels de programme à un fichier. Ensuite, tail -f ce fichier. De cette façon, ça devrait fonctionner... J'espère.

Lorsque vous redémarrez l'appel de ce programme, vous devrez effacer le fichier ou ajouter des bêtises pour éviter qu'il ne corresponde immédiatement à ce que vous cherchiez.

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