"Osserva" l'output di un comando fino a quando non viene osservata una particolare stringa e quindi esce


29

Sto cercando un modo per guardare a livello di codice l'output di un comando fino a quando non viene osservata una stringa particolare e quindi esci. Questo è molto simile a questa domanda, ma invece di mettere in coda un file, voglio "codificare" un comando.

Qualcosa di simile a:

guarda -n1 my_cmd | grep -m 1 "String Sto cercando"

(Ma questo non funziona per me.)

AGGIORNAMENTO: Devo chiarire che 'my_cmd' non emette continuamente testo ma deve essere ripetutamente chiamato fino a quando non viene trovata la stringa (motivo per cui ho pensato al comando 'watch'). A questo proposito, 'my_cmd' è come molti altri comandi unix come: ps, ls, lsof, last, ecc.


Avrei pensato che fosse possibile tail -fun output del programma e un file ... Sbaglio?
Joanis,

@Joanis. Hai ragione, ma nel mio caso 'my_cmd' non produce continuamente output e deve essere ripetutamente chiamato (proprio come la maggior parte dei comandi: ps, ls, lsof, ecc.)
gdw2

Risposte:


41

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 facilitare la CPU.

Il ciclo viene eseguito fino a quando grep trova la stringa nell'output del comando. -m 1significa "una partita è sufficiente", ovvero grep interrompe la ricerca dopo aver trovato la prima corrispondenza.

È inoltre possibile utilizzare grep -qche si chiude anche dopo aver trovato la prima corrispondenza, ma senza stampare la riga corrispondente.


una spiegazione di questo comando sarebbe apprezzata.
Mark W,

@MarkW: aggiornato.
Choroba,

qualcun altro ha menzionato grep -qquale è un'altra opzione. grep si chiude dopo aver trovato la stringa.
Dom

si noti che questo comando eseguirà ripetutamente il comando in questione, il che potrebbe essere o non essere desiderabile.
Adrien,

1
@A__: è auspicabile, come indicato nel PO in "Aggiornamento".
Choroba,

11
watch -e "! my_cmd | grep -m 1 \"String Im Looking For\""
  • ! annulla il codice di uscita della pipeline di comando
  • grep -m 1 esce quando viene trovata la stringa
  • watch -e ritorna se si è verificato un errore

Ma questo può essere migliorato per visualizzare effettivamente quella linea abbinata, che viene gettata via finora.


Grazie per la spiegazione dettagliata, ma non funziona per me. Il mio watchcomando (CentOS) non ha il -eflag (che non dovrebbe davvero importare). Ancora più importante, tuttavia, quando viene trovata la stringa, l'orologio continua a funzionare e non si chiude. Sembra che quando grep -mesce, esce solo uccide my_cmd, ma non watch.
gdw2,

No, è importante !, il flag "-e" è un suggerimento per lasciare l'orologio quando il comando ha un codice di errore diverso da 0. Poiché il suo orologio non presente sta per continuare sulla tua piattaforma. Comunque, buono a sapersi, sulla mia installazione di Ubuntu 11.10 va tutto bene. A volte ho anche problemi con Mac OSX per quanto riguarda strumenti da riga di comando molto obsoleti e sto usando le porte mac finora per ottenere un software più aggiornato.
matematica

Questo si interrompe se viene trovato il modello, ma non mostra alcun output fino a quando ciò non accade
Mark

Puoi impiegarlo teeper questo, ma questo introduce una nuova linea fuorviante, non so come aggirare ora:watch -n1 -e "! date | tee /dev/tty | grep --color -m 1 \"17\""
matematica

Sì, questo non ha funzionato per me. watchsmette diligentemente di guardare quando viene trovata la stringa, ma in realtà non esce finché non si preme un tasto. Così vicino.
mlissner

8

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, esce, il che chiude stdout sul processo che viene reindirizzato a grep. Questo evento dovrebbe naturalmente causare la chiusura regolare del programma, purché il processo riscriva nuovamente .

Quello che accadrà è che il processo riceverà un SIGPIPE quando tenta di scrivere su stdout chiuso dopo che grep è uscito. Ecco un esempio con ping, che altrimenti verrebbe eseguito indefinitamente:

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

Questo comando corrisponderà al primo 'pong' eseguito correttamente, quindi uscirà la volta successiva che pingtenta di scrivere su stdout.


Tuttavia,

Non è sempre garantito che il processo scriva di nuovo su stdout e quindi potrebbe non causare la generazione di un SIGPIPE (ad esempio, ciò può accadere quando si esegue la coda di un file di registro). La migliore soluzione che sono riuscito a trovare per questo scenario prevede la scrittura su un file; commenta se pensi di poter migliorare:

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

Abbattere questo:

  1. tail -f log_file & echo $! > pid- Tails un file, allega il processo allo sfondo e salva il PID ( $!) in un file. Ho provato invece ad esportare il PID in una variabile, ma sembra che ci sia una condizione di competizione tra qui e quando il PID viene riutilizzato.
  2. { ... ;}- raggruppa questi comandi in modo da poter convogliare l'output a grep mantenendo il contesto corrente (aiuta quando si salvano e riutilizzano le variabili, ma non siamo riusciti a far funzionare quella parte)
  3. | - pipe stdout lato sinistro allo stdin lato destro
  4. grep -m1 "find_me" - trova la stringa di destinazione
  5. && kill -9 $(cat pid)- force kill (SIGKILL) dopo aver terminato il tailprocesso una volta trovata la stringa corrispondente grep
  6. && rm pid - rimuovi il file che abbiamo creato

0
my_cmd | tail +1f | sed '/String Im Looking For/q'

Se tailnon supporta la +1fsintassi, prova tail -f -n +1. (Gli -n +1dice di iniziare all'inizio; tail -fper impostazione predefinita inizia con le ultime 10 righe di output.)


Si prega di consultare il mio aggiornamento alla domanda.
gdw2,

0

Aggiungi il risultato delle chiamate del tuo programma a un file. Quindi tail -fquel file. In questo modo dovrebbe funzionare ... spero.

Quando si riavvia la chiamata a quel programma, è necessario cancellare il file o aggiungere un po 'di senso senza senso, in modo che non corrisponda immediatamente a quello che stavi cercando.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.