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 ping
pró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:
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.
{ ... ;}
- 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)
|
- przesuń rurkę z wejścia standardowego do wejścia z prawej strony
grep -m1 "find_me"
- znajdź docelowy ciąg
&& kill -9 $(cat pid)
- force kill (SIGKILL) tail
proces po grep
wyjściu, gdy znajdzie pasujący ciąg
&& rm pid
- usuń utworzony przez nas plik
tail -f
jest wyjście programu tak samo jak pliku ... Czy się mylę?