Как применить фильтр к выводу `tail -f` в реальном времени?

60
tail -f path

Вышеприведенное приведёт к немедленному выводу изменений в файл, но я хочу применить фильтр к выводу, показывать только тогда, когда в нем есть ключевое слово xxx.

Как подойти к этому?

WAMP
источник
1
Пометка ответов как принятых помогает другим людям, которые читают ваши вопросы и их ответы, узнать, какой ответ может с большей вероятностью помочь им, если у них возникнут аналогичные вопросы или проблемы. Вы можете вернуться к своим предыдущим вопросам, нажав на свое имя пользователя.
Деннис Уильямсон

Ответы:

84

С Unix вы можете направить вывод одной программы в другую.

Так что для фильтрации tail вы можете использовать grep:

tail -f path | grep your-search-filter
AddersUK
источник
Но допустим, у вас есть 100 строк в конце (конец файла), и эти строки вы хотите отфильтровать. Ваше решение
TraderJoeChicago
1
Если вы хотите искать только последние 100 строк файла, попробуйте tail -100 path | grep xxx
AddersUK
15

Краткий ответ: tail -f somefile | grep somepattern

Тем не менее, это, как правило, не хватает. Допустим, вы отслеживаете файл, который часто поворачивается (если это журнал отладки, он может вращаться несколько раз). В этом случае tail -Fтвой друг. Я позволю тебе посмотреть разницу.

Но tail -fи tail -Fраспечатать кучу линий первых, что часто нежелательно в этом сценарии использования, так как в этом случае оных-n0

tail -F -n0 somefile | grep somepattern

Это будет хорошо до тех пор, пока вы не захотите сделать какую-то другую фильтрацию, а затем вам нужно остерегаться буферизации. stdout буферизуется по умолчанию при записи в терминал, но при полной буферизации при записи в канал. Таким образом, следующее будет испускать строки, как только они будут найдены, потому что они tailявно буферизуются (или сбрасывают свои выходные данные в конце каждой строки), а grepтакже буферизуются, потому что их выходные данные отправляются на ваш терминал:

tail -F -n0 somefile | grep somepattern

Но затем вы решаете использовать что-то подобное awkили cutдля дальнейшей обработки вывода.

tail -F -n0 somefile | grep somepattern | awk '{print $3}'

И теперь вы задаетесь вопросом, куда ушли ваши выходные данные ... в зависимости от объема журналов вы можете обнаружить, что вы получаете выходные данные, но это будет страница за раз, потому что теперь стандартный вывод grepработает в полностью буферизованном виде, и таким образом awkполучает это ввод 4kB за один раз (по умолчанию).

В этом случае вы можете указать grepвсегда делать буферизованную строку stdout, используя --line-bufferedопцию.

tail -F -n0 somefile | grep --line-buffered somepattern | ...

Однако большинство команд не имеют аналога --line-buffered. В случае более скриптовых инструментов вы можете использовать функцию для очистки вывода (например, in awk, функция is fflush(), которая имеет то же имя, что и ее аналог C, инструменты, такие как Perl и Python, имеют нечто подобное).

С такими cutкак ты скорее всего не повезло; ... но вы можете попробовать поискать unbuffer, что, я думаю, что-то, предоставленное expectнабором инструментов (я никогда не использовал его).

Я надеюсь, что вы нашли это полезным.

Ура, Кэмерон

Кэмерон Керр
источник
Я действительно ценю объяснение того, почему это работает в режиме линейной буферизации. Это отличное понимание, спасибо.
Зеленый,
2

и вы можете использовать несколько каналов и greps, исключать вещи с помощью grep -v, получать регистр нечувствительности с помощью grep -i и т. д.

то есть: tail -100f / var / log / messages | grep -V ACPI | grep -i ata

начните с конца 100 строк и продолжайте хвост, сначала исключите все строки с ACPI, затем покажите строки с ata, ATA или любым их сочетанием.

Другой удобный вариант - это варианты ABC для строк After, Before и Context (строки до и после).

Рональд Поттол
источник