Usa un bucle:
until my_cmd | grep -m 1 "String Im Looking For"; do : ; done
En lugar de :
, puedes usar sleep 1
(o 0.2) para facilitar la CPU.
El bucle se ejecuta hasta que grep encuentra la cadena en la salida del comando. -m 1
significa "una coincidencia es suficiente", es decir, grep deja de buscar después de encontrar la primera coincidencia.
También puedes usar grep -q
que también se cierra después de encontrar la primera coincidencia, pero sin imprimir la línea correspondiente.
watch -e "! my_cmd | grep -m 1 \"String Im Looking For\""
!
niega el código de salida de la canalización de comandosgrep -m 1
sale cuando se encuentra una cadenawatch -e
devuelve si se ha producido algún error
Pero esto se puede mejorar para mostrar realmente esa línea coincidente, que hasta ahora se descarta.
Para aquellos que tienen un programa que escribe continuamente en stdout, todo lo que necesitan hacer es canalizarlo a grep con la opción 'coincidencia única'. Una vez que grep encuentre la cadena coincidente, saldrá, lo que cierra la salida estándar en el proceso que se está canalizando a grep. Este evento debería naturalmente, hace que el programa salga correctamente siempre y cuando el proceso vuelva a escribir .
Lo que sucederá es que el proceso recibirá un SIGPIPE cuando intente escribir en la salida estándar cerrada después de que grep haya salido. Aquí hay un ejemplo con ping, que de otro modo se ejecutaría indefinidamente:
$ ping superuser.com | grep -m 1 "icmp_seq"
Este comando coincidirá con el primer 'pong' exitoso y luego saldrá la próxima vez ping
intenta escribir en stdout.
Sin embargo,
No siempre se garantiza que el proceso vuelva a escribir en la salida estándar y, por lo tanto, es posible que no genere un SIGPIPE (por ejemplo, esto puede suceder cuando se sigue un archivo de registro). La mejor solución que he encontrado para este escenario consiste en escribir en un archivo; por favor comente si cree que puede mejorar:
$ { tail -f log_file & echo $! > pid; } | { grep -m1 "find_me" && kill -9 $(cat pid) && rm pid; }
Desglosando esto:
tail -f log_file & echo $! > pid
- sigue un archivo, adjunta el proceso al fondo y guarda el PID ($!
) a un archivo. Intenté exportar el PID a una variable en su lugar, pero parece que hay una condición de carrera entre aquí y cuando se vuelve a usar el PID.{ ... ;}
- Agrupe estos comandos para que podamos canalizar la salida a grep mientras mantenemos el contexto actual (ayuda al guardar y reutilizar variables, pero no pudo hacer que esa parte funcionara)|
- canalizar la salida estándar del lado izquierdo a la entrada estándar del lado derechogrep -m1 "find_me"
- encuentra la cadena de destino&& kill -9 $(cat pid)
- fuerza matar (SIGKILL) eltail
proceso despuésgrep
sale una vez que encuentra la cadena coincidente&& rm pid
- eliminar el archivo que creamos