Почему не `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

Вы найдете больше информации и решений в связанном посте.

Другие вопросы по тегам