Почему не `tail -f … | grep -q …`выходить, когда находит совпадение?
Я делаю довольно стандарт tail
+ grep
:
tail -f some_log_file.txt | grep -q known-string
Если я запускаю команду без -q
:
tail -f some_log_file.txt | grep known-string
Я вижу вывод:
[Tue Feb 12 11:32:45 2019] known-string.
так что я знаю, что grep совпадает. Однако, когда я добавляю -q
команда grep не завершается, она просто висит там в ожидании дополнительных выходных данных... хотя на странице руководства написано, что она "немедленно завершится с нулевым статусом, если найдено какое-либо совпадение":
-q, --quiet, --silent Quiet; do not write anything to standard output. Exit immediately with zero status if any match is found, even if an error was detected. Also see the -s or --no-messages option.
Может кто-нибудь объяснить, почему -q
не вызывает ли мой grep выход? Я пытаюсь связать && beep
до конца, так что grep
подает звуковой сигнал, когда найдено совпадение, но если я не смогу его завершить, это не сработает.
2 ответа
grep
выходит и труба уходит, хотя tail
продолжает бежать. Этот журнал отчетов об ошибках начинается с варианта использования, очень похожего на ваш:
Я хочу использовать
tail
а такжеgrep
следовать за файлом, пока не появится определенный шаблон. Ноtail
не выходит когдаgrep
закончен.$ echo xxx > /tmp/blabla $ tail -f /tmp/blabla |grep -m1 --line-buffered "xxx" xxx
Сейчас
tail
все еще пытается прочитать и выходит, только если я снова пишу в/tmp/blabla
,Это так и должно быть?
Объяснение там:
tail
выходит на SIGPIPE, однако он будет только получать сигнал наwrite()
и поэтому вам нужно получить больше данных в файле, прежде чемtail
выйдет.
Насколько я знаю, этот точный механизм очень распространен. Многие инструменты выходят после того, как они пытаются что-то записать в сломанную трубу, это не ошибка.
Затем пришло это желание:
Это справедливо, хотя
tail
Так как он может висеть вечно, следует предпринять специальные шаги, чтобы реагировать на уходящий конец трубы.
И наконец:
Реализовано в:
https://git.sv.gnu.org/cgit/coreutils.git/commit/?id=v8.27-42-gce0415f
И действительно, когда я пытаюсь воспроизвести вашу проблему с tail
из GNU coreutils 8.28 я не могу. Инструмент выходит немедленно.
Из сообщения StackOverflow "grep -q" не завершается с "tail -f":
tail -f
будет читать файл и отображать строки, добавленные позже, он не прекратит работу (если сигнал неSIGTERM
отправлено).grep
здесь не блокирующая часть,tail -f
является.grep
будет читать из трубы, пока она не закроется, но это никогда не происходит, потому чтоtail -f
не выходит и держать трубу открытой.Решение вашей проблемы, вероятно, будет (не проверено и, скорее всего, будет плохо работать):
tail -f logfile | while read line; do echo $line | grep -q 'find me to quit' && break; done
Вы найдете больше информации и решений в связанном посте.