„Obserwuj” wynik polecenia, aż do zaobserwowania określonego ciągu, a następnie wyjdź

29

Szukam sposobu, aby programowo obserwować wyjście polecenia, dopóki nie zostanie zaobserwowany określony ciąg, a następnie wyjść. Jest to bardzo podobne do tego pytania, ale zamiast ogoniać plik, chcę „ogonić” polecenie.

Coś jak:

obejrzyj -n1 my_cmd | grep -m 1 „Ciąg szukam”

(Ale to nie działa dla mnie.)

AKTUALIZACJA: Muszę wyjaśnić, że „my_cmd” nie wysyła w sposób ciągły tekstu, ale musi być wielokrotnie wywoływany, dopóki nie zostanie znaleziony ciąg znaków (dlatego pomyślałem o poleceniu „obserwuj”). Pod tym względem „my_cmd” jest podobny do wielu innych poleceń unixowych, takich jak: ps, ls, lsof, last itp.

gdw2
źródło
Wydawało mi się, że możliwe tail -fjest wyjście programu tak samo jak pliku ... Czy się mylę?
Joanis,
@Joanis. Masz rację, ale w moim przypadku „my_cmd” nie generuje w sposób ciągły danych wyjściowych i musi być wielokrotnie wywoływane (podobnie jak większość poleceń: ps, ls, lsof itp.)
gdw2

Odpowiedzi:

41

Użyj pętli:

until my_cmd | grep -m 1 "String Im Looking For"; do : ; done

Zamiast tego :możesz użyć sleep 1(lub 0.2), aby ułatwić procesor.

Pętla działa, dopóki grep nie znajdzie łańcucha w danych wyjściowych polecenia. -m 1oznacza „wystarczy jedno dopasowanie”, tzn. grep przestaje wyszukiwać po znalezieniu pierwszego dopasowania.

Możesz także użyć polecenia, grep -qktóre kończy pracę po znalezieniu pierwszego dopasowania, ale bez drukowania pasującej linii.

choroba
źródło
wyjaśnienie tego polecenia byłoby mile widziane.
Mark W
@ MarkW: Zaktualizowano.
choroba
ktoś inny wspomniał, grep -qco jest inną opcją. grep kończy pracę po znalezieniu ciągu.
niedz.
zwróć uwagę, że to polecenie będzie wielokrotnie uruchamiać dane polecenie, co może, ale nie musi być pożądane.
adrien
1
@A__: Pożądane jest, jak stwierdzono w PO w części „Aktualizacja”.
choroba
11
watch -e "! my_cmd | grep -m 1 \"String Im Looking For\""
  • ! neguje kod wyjścia potoku poleceń
  • grep -m 1 kończy się po znalezieniu ciągu
  • watch -e zwraca, jeśli wystąpił jakikolwiek błąd

Ale można to poprawić, aby wyświetlać tę dopasowaną linię, która jest wyrzucana do tej pory.

matematyka
źródło
Dzięki za szczegółowe wyjaśnienie, ale to nie działa dla mnie. Moje watchpolecenie (CentOS) nie ma -eflagi (co nie powinno tak naprawdę mieć znaczenia). Co ważniejsze, po znalezieniu łańcucha zegarek nadal działa i nie wychodzi. Wygląda na to, że kiedy grep -mwychodzi, wychodzi tylko z zabójstw my_cmd, ale nie watch.
gdw2
Nie, to ma znaczenie !, flaga „-e” oznacza opuszczenie zegarka, gdy komenda ma kod błędu inny niż 0. Ponieważ nieobecny zegarek ma zamiar kontynuować na twojej platformie. W każdym razie dobrze wiedzieć, że w mojej instalacji Ubuntu 11.10 wszystko jest w porządku. Czasami mam również problemy z Mac OSX dotyczące bardzo przestarzałych narzędzi wiersza poleceń i do tej pory używam portów Mac, aby uzyskać bardziej aktualne oprogramowanie.
matematyka
Zatrzymuje się, jeśli wzorzec zostanie znaleziony, ale nie wyświetla żadnych danych wyjściowych, dopóki tak się nie stanie
Mark
Możesz teedo tego zatrudnić , ale wprowadza to wprowadzającą w błąd nową linię, nie wiem jak teraz obejść:watch -n1 -e "! date | tee /dev/tty | grep --color -m 1 \"17\""
matematyka
Tak, to nie działało dla mnie. watchposłusznie przestaje oglądać, gdy łańcuch zostanie znaleziony, ale tak naprawdę nie wychodzi, dopóki nie naciśniesz klawisza. Tak blisko.
mlissner
8

Dla tych, którzy mają program, który ciągle pisze na standardowe wyjście, wszystko, co musisz zrobić, to potokować go grep za pomocą opcji „single match”. Gdy grep znajdzie pasujący ciąg, zakończy działanie, co zamyka standardowe wyjście procesu, który jest przesyłany do grep. To zdarzenie powinno naturalnie spowodować, że program z wdziękiem zakończy działanie , o ile proces zacznie ponownie pisać .

Stanie się tak, że proces otrzyma SIGPIPE, gdy spróbuje napisać do zamkniętego wyjścia po wyjściu z grep. Oto przykład z pingiem, który w innym przypadku działałby w nieskończoność:

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

To polecenie pasuje do pierwszego udanego „ponga”, a następnie kończy pracę przy następnej pingpróbie zapisu na standardowe wyjście.


Jednak,

Nie zawsze jest zagwarantowane, że proces ponownie zapisze na standardowym wyjściu i dlatego może nie spowodować podniesienia SIGPIPE (np. Może się to zdarzyć podczas modyfikowania pliku dziennika). Najlepsze rozwiązanie, jakie udało mi się wymyślić w tym scenariuszu, polega na zapisaniu do pliku; prosimy o komentarz, jeśli uważasz, że możesz poprawić:

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

Podział tego:

  1. tail -f log_file & echo $! > pid- dołącza plik do pliku, dołącza proces do tła i zapisuje PID ( $!) w pliku. Zamiast tego próbowałem wyeksportować PID do zmiennej, ale wygląda na to, że pomiędzy tym miejscem a tym, kiedy PID zostanie ponownie użyty, istnieje warunek wyścigu.
  2. { ... ;}- zgrupuj te polecenia razem, abyśmy mogli przesyłać dane wyjściowe do grep, zachowując bieżący kontekst (pomaga przy zapisywaniu i ponownym użyciu zmiennych, ale nie był w stanie uruchomić tej części)
  3. | - przesuń rurkę z wejścia standardowego do wejścia z prawej strony
  4. grep -m1 "find_me" - znajdź docelowy ciąg
  5. && kill -9 $(cat pid)- force kill (SIGKILL) tailproces po grep wyjściu, gdy znajdzie pasujący ciąg
  6. && rm pid - usuń utworzony przez nas plik
Blake Regalia
źródło
0
my_cmd | tail +1f | sed '/String Im Looking For/q'

Jeśli tailnie obsługuje +1fskładni, spróbuj tail -f -n +1. ( -n +1Mówi, że ma zacząć od początku; tail -fdomyślnie zaczyna się od ostatnich 10 wierszy wyniku).

Keith Thompson
źródło
Proszę zobaczyć moją aktualizację pytania.
gdw2
0

Dołącz wynik wywołania programu do pliku. Potem tail -ften plik. W ten sposób powinno działać ... Mam nadzieję.

Po ponownym uruchomieniu tego programu musisz usunąć plik lub dodać do niego bełkot, aby od razu nie pasował do tego, czego szukałeś.

Joanis
źródło