Можно ли использовать grep
для непрерывного потока?
Я имею в виду некоторую команду tail -f <file>
, но с grep
на выходе, чтобы сохранить только интересующие меня строки.
Я пробовал tail -f <file> | grep pattern
, но кажется, что grep
может выполняться только один раз tail
заканчивается, то есть никогда.
Включите режим буферизации строки grep
при использовании BSD grep (FreeBSD, Mac OS X и т.д.)
tail -f file | grep --line-buffered my_pattern
Вам не нужно делать это для GNU grep (используется практически во всех Linux), поскольку он будет сбрасываться по умолчанию (YMMV для других Unix-подобных приложений, таких как SmartOS, AIX или QNX).
Я использую tail -f <file> | grep <pattern>
все время.
Он будет ждать, пока grep не начнет сбрасываться, пока он не закончится (я использую Ubuntu).
Я думаю, что ваша проблема в том, что grep использует некоторую буферизацию вывода. Попробуйте
tail -f file | stdbuf -o0 grep my_pattern
он установит режим буферизации вывода grep небуферизованным.
grep
.
unbuffer
(в пакете expect-dev
на debian) является королем . Так что я бы использовал unbuffer поверх stdbuf.
В большинстве случаев вы можете tail -f /var/log/some.log |grep foo
, и он будет работать нормально.
Если вам нужно использовать несколько grep в работающем файле журнала, и вы обнаружите, что у вас нет выхода, вам может понадобиться вставить переключатель --line-buffered
в grep (s) средний, например так:
tail -f /var/log/some.log | grep --line-buffered foo | grep bar
Если вы хотите найти совпадения во всем файле (а не только в хвосте), и вы хотите, чтобы он сидел и ждал новых совпадений, это прекрасно работает:
tail -c +0 -f <file> | grep --line-buffered <pattern>
Флаг -c +0
указывает, что выход должен начинаться с 0
bytes (-c
) с начала (+
) файла.
Не видел, чтобы кто-нибудь предложил мое обычное решение для этого:
less +F <file>
ctrl + c
/<search term>
<enter>
shift + f
Я предпочитаю это, потому что вы можете использовать ctrl + c
для остановки и навигации по файлу в любое время, а затем просто нажать shift + f
чтобы вернуться к поиску в реальном времени.
sed будет лучшим выбором (редактор потоков)
tail -n0 -f <file> | sed -n '/search string/p'
и затем, если вы хотите, чтобы команда tail выходила, как только вы нашли конкретную строку:
tail --pid=$(($BASHPID+1)) -n0 -f <file> | sed -n '/search string/{p; q}'
Очевидно, что bashism: $ BASHPID будет идентификатором процесса команды tail. Команда sed будет следующей после tail в конвейере, поэтому идентификатор процесса sed будет $ BASHPID + 1.
$BASHPID+1
), будет вашим, во многих ситуациях ложно, и это ничего не делает для решения проблемы буферизации, о которой, вероятно, пытался спросить OP. В частности, рекомендация sed
grep
здесь кажется просто вопросом (сомнительного) предпочтения. (Вы можете получить поведение p;q
с помощью grep -m 1
если вы пытаетесь достичь этого.)
--line-buffered
нет. Я искренне не понимаю минус 1.
вы можете рассмотреть этот ответ как улучшение. Обычно я использую
tail -F <fileName> | grep --line-buffered <pattern> -A 3 -B 5
-F лучше в случае поворота файла (-f не будет работать должным образом, если файл повернут)
-A и -B полезно для получения строк непосредственно перед и после появления шаблона.. эти блоки появятся между разделителями пунктирных линий
grep -C 3 <pattern>
, заменяет -A <N> и -B <N>, если N одинаково.
Эта команда работает для меня (Suse):
mail-srv:/var/log # tail -f /var/log/mail.info |grep --line-buffered LOGIN >> logins_to_mail
сбор логинов к почтовому сервису
Да, на самом деле все будет хорошо. Grep
, и большинство команд Unix работают по потокам по одной строке за раз. Каждая строка, которая выходит из хвоста, будет анализироваться и передаваться, если она соответствует.
grep
является последней командой в цепочке каналов, она будет действовать так, как вы объясните. Однако, если он находится посередине, он будет буферизовать около 8 тыс. Выводов одновременно.
Используйте awk (еще одна полезная утилита bash) вместо grep, где у вас нет опции для буферизации строк! Он будет непрерывно передавать ваши данные из хвоста.
вот как вы используете grep
tail -f <file> | grep pattern
Вот как вы будете использовать awk
tail -f <file> | awk '/pattern/{print $0}'
{print $0}
является избыточным, поскольку печать является действием по умолчанию при выполнении условия.)
tail -f file
(я вижу новый вывод в реальном времени)