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 commandegrep -m 1
se ferme lorsque la chaîne est trouvéewatch -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 :
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é.{ ... ;}
- 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)|
- diriger la sortie standard du côté gauche vers la sortie standard du côté droitgrep -m1 "find_me"
- trouver la chaîne cible&& kill -9 $(cat pid)
- forcer à tuer (SIGKILL) letail
traiter aprèsgrep
quitte une fois qu'il trouve la chaîne correspondante&& rm pid
- supprimer le fichier que nous avons créé