tail -f, но с номерами строк

21

Я пытаюсь увидеть, сколько раз foo barв /var/log/foo.logтечение произвольного промежутка времени появляется на удаленном сервере, но ничего из того, что я пробовал до сих пор, не сработало.

У меня уже есть сценарий таймера, который я использую для отслеживания того, сколько времени прошло с тех пор, как я начал хвастаться /var/log/foo.log, и теперь я просто хотел бы узнать, сколько раз foo barпоявилось в хвостовом выводе.

Я искал в Google, но я не нашел ничего подходящего в первых 10 страницах результатов.

Вот что я пробовал с разочаровывающими результатами:

## works on local machine, but doesn't work as expected on remote
tail -f /var/log/foo.log | grep foo\ bar | sed '='

## works on local, but not remote
tail -f /var/log/foo.log | grep foo\ bar | cat -n -

##  works on local, but not remote
tail -f /var/log/foo.log | grep foo\ bar | awk -F'\n' '{printf "[%d]> ", NR; print $1}'

Я даже пытался написать сценарий sed, который бы вел себя как tail -f, но я сделал это с ограничением на успех.

НОТА

на удаленном сервере запущена более старая версия coreutils, и обновление является опцией, но никоим образом НЕ является желаемым решением.

Алексей Магура
источник
2
Каким образом это не работает? Попробуйте --line-bufferedвариант grep. Илиtail -f ... | awk '/foo bar/{print ++n, $0}'
Стефан Шазелас
Почему это не работает на пульте? Пример:tail -f /var/log/log.log | awk '{ printf "[%d]> %s\n", NR+1 ,$0; fflush(stdout); }'

Ответы:

29
tail -f | nl

работает для меня и является первым, о чем я подумал - это если вы действительно хотите, чтобы строки были пронумерованы от 1, а не от реального номера строки из просматриваемого файла. При необходимости добавьте, grepесли необходимо, в соответствующее место (до или после nl). Однако помните, что буферизация может произойти. В моем конкретном случае grepесть --line-bufferedопция, но nlона буферизует вывод и не имеет возможности отключить ее. Следовательно, tail | nl | grepкомбо не очень красиво.

Это сказало,

tail -f | grep -n pattern

у меня тоже работает. Нумерация начинается снова с начала «хвоста», а не с начала всего файла журнала.

peterph
источник
версия grep, запущенная на сервере, не имеет -nопции.
Алексей Магура
у него, однако, есть длинный вариант --line-number: tail -f /var/log/foo.log | grep foo\ bar --line-numberработает!
Алексей Магура
1
Это интересно - я не проверял POSIX как таковой, но на странице GNU grep говорится: -n указывается в POSIX .
Петер
16

Я думаю, что это лучше ..

less -N +F <filepath>
Адам Эберлин
источник
2
Не могли бы вы объяснить, почему вы думаете, что это лучше?
Навигатрон
Это большое редактирование, я возвращаюсь.
Адам Эберлин
3
Показывает номер строки, принимая в качестве ссылки весь файл. хвост -f | nl показывает номер строки, принимая за первый вывод tail.
rafaelvalle
Это очень удобно и касается названия ОП, но не их вопроса . Они хотели знать, сколько раз X появляется в файле: P
Тимма
6

Вы также можете перенаправить вывод less, у него есть функция номера строки, -Nкоторая позволит вам прокручивать журнал назад и вперед.

$ tail -f /var/log/foo.log | less -N

пример

  1 Jan 17 22:11:58 greeneggs fprintd[4323]: ** Message: entering main loop
  2 Jan 17 22:12:01 greeneggs su: (to root) saml on pts/5
  3 Jan 17 22:12:28 greeneggs fprintd[4323]: ** Message: No devices in use, exit
  4 Jan 17 22:12:56 greeneggs gnome-session[1876]: 22:12:56 | Git | personal_repo | Checking for remote changes...
  5 Jan 17 22:12:56 greeneggs gnome-session[1876]: 22:12:56 | Cmd | personal_repo | git rev-parse HEAD
  6 Jan 17 22:12:56 greeneggs gnome-session[1876]: 22:12:56 | Cmd | personal_repo | git ls-remote --heads --exit-code "ssh://sam@sparkleshare.jake      
  6 8us.org/home/sam/SparkleShare/personal_repo.git" master
  7 Jan 17 22:12:58 greeneggs gnome-session[1876]: X11 forwarding request failed on channel 1
  8 Jan 17 22:12:58 greeneggs gnome-session[1876]: 22:12:58 | Git | personal_repo | No remote changes, local+remote: 532213be48cce3b93cb177d409faa      
  8 03b71d0cfa5
  9 Jan 17 22:13:35 greeneggs gnome-session[1876]: 22:13:35 | ListenerTcp | Pinging tcp://notifications.sparkleshare.org:443/
 10 Jan 17 22:13:35 greeneggs gnome-session[1876]: 22:13:35 | ListenerTcp | Received pong from tcp://notifications.sparkleshare.org:443/

ПРИМЕЧАНИЕ. Обратите внимание на вывод. Эта функция может вам понравиться, а может и не понравиться, но она займет длинные строки и нарежет их так, чтобы они продолжались на следующей строке, но сохраняли тот же соответствующий номер строки. Я считаю, что эта функция неоценима при анализе широких файлов журналов! Вы можете увидеть эффект этой функции в строках 6 и 8 .

SLM
источник
Это неясно. Где указано имя файла? Следует пояснить, что выходные данные нумеруются с 1, начиная с последних 10 строк имени файла, так как это поведение по умолчанию tail. Что касается длинных строк, то это поведение переключается при lessиспользовании -S.
ILMostro_7
2

Чтобы отобразить новые строки только в файле журнала, так как они идут вместе с номером строки, вы можете сделать:

{
  initial_lines=$(wc -l)
  tail -n +1 -f | awk -v NR="$initial_lines" '/pattern/{print NR": "$0}'
} < file.log

(с помощью mawk, вы захотите добавить -Winteractiveопцию, чтобы предотвратить ее входную (!) буферизацию).

wc -lчитает строки , которые уже были там, и считает их (символы новой строки, что означает, что он все еще работает, даже если последняя строка еще не заполнена), а затем мы tail -fостальное (начиная с того места, где wcпрекратили чтение) и сообщаем, awkкакой номер строки первый это видит.

Стефан Шазелас
источник
выбор l качестве имени переменной заставил меня прищуриться на $ l, думая, что это $1^^ (но, как я знаю (и на 100% доверяю) вам, я перечитал и увидел правду). Просто для любопытства: чтобы избежать некоторого «состояния гонки» между wc -lи tail -f(если файл быстро растет, можно отбросить некоторые строки и, следовательно, NR начинается с неправильного числа), можно ли $lвместо этого пропустить строки? (а какой предел для хвоста -nв posix и в gnu?). Может быть, с временным промежуточным файлом?
Оливье Дюлак
@OlivierDulac, tail -n +1(прочитайте что-нибудь из начальной позиции) решает проблемы состояния гонки. Он будет читать строки, которых не было в файле на момент wc -lзавершения, с точной позиции, wcоставленной им. Таким образом, NR будет иметь правильную позицию независимо от того, сколько строк написано между wcокончанием и tailначалом. Если вы скажете tailначать с некоторой позиции относительно конца файла, у вас возникнут проблемы.
Стефан
о, интересно: действительно, данные накапливаются в stdin, в то время как ничто не читает их (между концом wc и началом головы) ... Я должен был понять это. Спасибо. Теперь я понимаю, почему вы "<файл". умный, как обычно :)
Оливье Дюлак
1
@OlivierDulac, об ограничениях (которые здесь не применимы tail -n +1), для обычных файлов у большинства реализаций нет таковых, поскольку они могут начинаться с конца и seekобратно, пока не найдут n-ную новую строку без необходимости хранить более одного значения buf данных в памяти. Для ввода без поиска, вот где вы можете столкнуться с ограничениями. POSIX требует, чтобы реализации могли хранить по крайней мере 10 х LINE_MAX байт (LINE_MAX по крайней мере 2048). У хвоста GNU нет никаких ограничений, кроме памяти AFAIK
Стефан
0

Если вы хотите начать нумерацию с самого начала, вам понадобится grep -n для применения ко всем строкам.

 tail -f -n100000000 filename.log | grep -n '' 

Если бы тогда вы хотели показать только последние 10, я бы подумал, что вы можете изменить файл:

 tail -f -n100000000 filename.log | grep -n '' | tail -n10

Первый удобен, но показывает слишком много продукции. Я не знаю, почему второй не работает.

Мартин Кливер
источник
Хвост не имеет «показать все линии», следовательно, мой 100000000
Мартин Кливер
1
tail -n +1 -fхвост с самого начала.
Стефан
1
Второй не работает, потому что самые правые tailне могут ничего выводить, пока не увидят последнюю строку своего ввода (как он узнает, какая десятая последняя строка?), Что никогда не произойдет, как tail -fникогда не останавливается.
Стефан
-1

Команда cat -n [filename] | tailбыстро подсчитает и отобразит самые последние записи, если это то, что вы ищете.

-fПереключатель делает его стойким до побега - который на самом деле не звучит применимо в вашем сценарии или является излишним.

wc -l [filename] получит количество строк в цели

wc -l [filenameprefix]* будет подсчитывать все строки во всех файлах, соответствующих шаблону, и даже сообщать итоговую сумму в конце.

Более полная информация может дать более полные ответы.

OtisM
источник
-1

Это аргумент nили --lines(используется немного по-другому, см. Ниже):

$ tail -f -n 25 /path/to/file.txt

$ tail -f --lines=25 /path/to/file.txt

Смотрите также помощь:

$ tail --help
automatix
источник
1
ОП хочет номера строк, а не количество строк.
robbat2