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 :
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é.
{ ... ;}
- 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)
|
- rediriger la sortie stdout du côté gauche vers l'entrée stdin du côté droit
grep -m1 "find_me"
- trouver la chaîne cible
&& kill -9 $(cat pid)
- forcer la terminaison (SIGKILL) du processus tail
après que grep
ait trouvé la chaîne correspondante et quitté
&& rm pid
- supprimer le fichier que nous avons créé