Usa un ciclo:
until my_cmd | grep -m 1 "String Im Looking For"; do : ; done
Invece di :
, puoi usare sleep 1
(o 0.2) per alleggerire la CPU.
Il ciclo viene eseguito finché grep non trova la stringa nell'output del comando. -m 1
significa "una corrispondenza è sufficiente", ovvero grep interrompe la ricerca dopo aver trovato la prima corrispondenza.
Puoi anche usare grep -q
che si chiude anche dopo aver trovato la prima corrispondenza, ma senza stampare la riga corrispondente.
watch -e "! my_cmd | grep -m 1 \"String Im Looking For\""
!
nega il codice di uscita della pipeline dei comandigrep -m 1
esce quando viene trovata una stringawatch -e
restituisce se si è verificato un errore
Ma questo può essere migliorato per visualizzare effettivamente quella linea abbinata, che finora è stata buttata via.
Per coloro che hanno un programma che scrive continuamente su stdout, tutto ciò che devi fare è reindirizzarlo a grep con l'opzione 'single match'. Una volta che grep trova la stringa corrispondente, uscirà, chiudendo lo stdout sul processo che viene reindirizzato a grep. Questo evento dovrebbe naturalmente fa sì che il programma esca normalmente fintanto che il processo scrive di nuovo .
Quello che accadrà è che il processo riceverà un SIGPIPE quando proverà a scrivere su stdout chiuso dopo che grep è uscito. Ecco un esempio con ping, che altrimenti verrebbe eseguito all'infinito:
$ ping superuser.com | grep -m 1 "icmp_seq"
Questo comando corrisponderà al primo 'pong' riuscito, quindi uscirà la volta successiva ping
prova a scrivere su stdout.
Tuttavia,
Non è sempre garantito che il processo scriva di nuovo su stdout e quindi potrebbe non causare l'innalzamento di un SIGPIPE (ad esempio, ciò può accadere durante il tailing di un file di registro). La migliore soluzione che sono riuscito a trovare per questo scenario prevede la scrittura su un file; per favore commenta se pensi di poter migliorare:
$ { tail -f log_file & echo $! > pid; } | { grep -m1 "find_me" && kill -9 $(cat pid) && rm pid; }
Analizzando questo:
tail -f log_file & echo $! > pid
- accoda un file, allega il processo in background e salva il PID ($!
) in un file. Ho provato invece a esportare il PID in una variabile, ma sembra che ci sia una condizione di competizione tra qui e quando il PID viene riutilizzato.{ ... ;}
- raggruppare questi comandi in modo da poter reindirizzare l'output a grep mantenendo il contesto corrente (aiuta quando si salvano e si riutilizzano le variabili, ma non è stato possibile far funzionare quella parte)|
- reindirizza lo stdout del lato sinistro allo stdin del lato destrogrep -m1 "find_me"
- trova la stringa di destinazione&& kill -9 $(cat pid)
- force kill (SIGKILL) iltail
processo dopogrep
esce una volta trovata la stringa corrispondente&& rm pid
- rimuovi il file che abbiamo creato