GNU/Linux >> Tutoriels Linux >  >> Linux

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

Utiliser une boucle :

until my_cmd | grep -m 1 "String Im Looking For"; do : ; done

Au lieu de : , vous pouvez utiliser sleep 1 (ou 0.2) pour alléger 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 la recherche après avoir trouvé la première correspondance.

Vous pouvez également utiliser grep -q qui se ferme également après avoir trouvé la première correspondance, mais sans imprimer la ligne correspondante.


watch -e "! my_cmd | grep -m 1 \"String Im Looking For\""
  • ! annule le code de sortie du pipeline de commande
  • grep -m 1 se ferme lorsque la chaîne est trouvée
  • watch -e renvoie si une erreur s'est produite

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


Pour ceux qui ont un programme qui écrit en permanence sur stdout, tout ce que vous avez à faire est de le diriger vers grep avec l'option 'single match'. Une fois que grep a trouvé la chaîne correspondante, il se ferme, ce qui ferme stdout sur le processus qui est redirigé vers grep. Cet événement devrait provoquent naturellement la sortie du programme avec élégance tant que le processus écrit à nouveau .

Ce qui se passera, c'est que le processus recevra un SIGPIPE lorsqu'il essaiera d'écrire sur une sortie standard fermée après la sortie de grep. Voici un exemple avec ping, qui s'exécuterait autrement indéfiniment :

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

Cette commande correspondra au premier "pong" réussi, puis quittera la prochaine fois ping essaie d'écrire sur stdout.

Cependant,

Il n'est pas toujours garanti que le processus écrira à nouveau sur stdout et ne provoquera donc pas la levée d'un SIGPIPE (par exemple, cela peut se produire lors de la fin 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 que vous pouvez vous améliorer :

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

Décomposition :

  1. tail -f log_file & echo $! > pid - suit un fichier, attache le processus à l'arrière-plan et enregistre le PID ($! ) dans un fichier. J'ai essayé d'exporter le PID vers une variable à la place, mais il semble qu'il y ait une condition de concurrence entre ici et le moment où le PID est à nouveau utilisé.
  2. { ... ;} - regrouper ces commandes afin que nous puissions rediriger la sortie vers grep tout en conservant le contexte actuel (aide lors de l'enregistrement et de la réutilisation de variables, mais n'a pas pu faire fonctionner cette partie)
  3. | - diriger la sortie standard du côté gauche vers la sortie standard du côté droit
  4. grep -m1 "find_me" - trouver la chaîne cible
  5. && kill -9 $(cat pid) - forcer à tuer (SIGKILL) le tail traiter après grep quitte une fois qu'il trouve la chaîne correspondante
  6. && rm pid - supprimer le fichier que nous avons créé

Linux
  1. Comment capturer les sessions de terminal et la sortie avec la commande de script Linux

  2. Sortie vers Stdout et en même temps Grep dans un fichier ?

  3. Comment supprimer la sortie de Grep, afin qu'elle ne renvoie que le statut de sortie ?

  4. $_ Vs !$. Dernier argument de la commande précédente et redirection de sortie ?

  5. Grep pour plusieurs chaînes dans des fichiers, puis répertorier les fichiers dans l'ordre de taille ?

Commande de sortie Bash et codes de sortie

Prettyping - Rendre la sortie de la commande Ping plus jolie et plus facile à lire

Utilisation de la commande grep sous Linux

Convertir une sortie en chaîne

Comment puis-je boucler sur la sortie d'une commande shell ?

Arrêter de regarder la sortie d'un programme particulier après avoir utilisé la commande watch ?