tail -f, mas com números de linha


21

Estou tentando ver quantas vezes foo baraparece /var/log/foo.logdentro de um período arbitrário em um servidor remoto, mas nada que eu tentei até agora funcionou.

Eu já tenho um script de cronômetro que eu uso para acompanhar quanto tempo se passou desde que comecei a seguir /var/log/foo.loge agora gostaria de saber como quantas vezes foo barapareceram na saída de cauda.

Pesquisei no google, mas não encontrei nada pertinente nas primeiras 10 páginas de resultados.

Aqui está o que eu tentei com resultados frustrantes:

## 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}'

Eu até tentei escrever um script sed que agisse assim tail -f, mas fiz um progresso limitado a nenhum com isso.

NOTA

o servidor remoto está executando uma versão mais antiga do coreutils e a atualização é uma opção, mas NÃO é de forma alguma a solução desejada.


2
De que maneira isso não funciona? Tente a --line-bufferedopção para grep. Outail -f ... | awk '/foo bar/{print ++n, $0}'
Stéphane Chazelas

Por que não funciona no controle remoto? Exemplo:tail -f /var/log/log.log | awk '{ printf "[%d]> %s\n", NR+1 ,$0; fflush(stdout); }'

Respostas:


29
tail -f | nl

funciona para mim e é o primeiro que eu pensei - ou seja, se você realmente deseja as linhas numeradas de 1 e não com o número real da linha do arquivo assistido. Opcionalmente, adicione grepse necessário ao local apropriado (antes ou depois nl). No entanto, lembre-se de que pode ocorrer buffer. No meu caso particular, greptem a --line-bufferedopção, mas nlarmazena em buffer a saída e não tem a opção de desativá-la. Portanto, o tail | nl | grepcombo não flui muito bem.

Dito isto,

tail -f | grep -n pattern

funciona para mim também. A numeração começa novamente a partir do início do "final" em vez de iniciar o arquivo de log inteiro.


a versão do grep em execução no servidor não tem uma -nopção.
Alexej Magura

no entanto, tem a opção longa --line-number: tail -f /var/log/foo.log | grep foo\ bar --line-numberfunciona!
precisa saber é o seguinte

1
Isso é interessante - eu não verifiquei o POSIX como tal, mas a página de manual do GNU grep diz: -n é especificado pelo POSIX .
Peterph

16

Eu acho que isso é melhor ..

less -N +F <filepath>

2
Você poderia explicar por que acha melhor?
Navigatron

Esta é uma edição grande, estou revertendo.
Adam Eberlin

3
Mostra o número da linha, tomando como referência o arquivo inteiro. cauda -f | nl mostra o número da linha tomando como referência a primeira saída da cauda.
Rafaelvalle

Isso é muito útil e aborda o título do OP, mas não a pergunta deles . Eles queriam saber quantas vezes o X aparece em um arquivo: P
Timmah

6

Você também pode canalizar a saída para less, pois ela possui um recurso de número de linha, o -Nque permitiria rolar para frente e para trás no log.

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

Exemplo

  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/

NOTA: Observe a saída. Você pode ou não gostar desse recurso, mas ele terá linhas longas e as cortará para que continuem na próxima linha, mas ainda mantenha o mesmo número de linha correspondente. Acho esse recurso inestimável ao analisar arquivos de log que são amplos! Você pode ver o efeito desse recurso nas linhas 6 e 8 .


Isso não está claro. Onde o nome do arquivo é especificado? Deve ser esclarecido, observando que a saída é numerada de 1 começando com as últimas 10 linhas do nome do arquivo, pois esse é o comportamento padrão de tail. Quanto às longas filas, esse comportamento é alternado no lessuso -S.
ILMostro_7

2

Para grep novas linhas apenas no arquivo de log como elas vêm com o número de linha, você pode:

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

(com mawk, você desejará adicionar a -Winteractiveopção para impedir seu buffer de entrada (!)).

wc -llê as linhas que já estavam lá e as conta (os caracteres de nova linha, o que significa que ainda funciona mesmo que a última linha ainda não esteja cheia), e depois tail -fo resto (a partir de onde wcparou de ler) e diz awkqual é o número da linha de o primeiro que vê.


escolher lo nome da variável me fez apertar os olhos para $ 1, pensando que era $1^^ (mas como eu conheço (e 100% confio) em você, reli e vi a verdade). Apenas por curiosidade: para evitar alguma "condição de corrida" entre o wc -le o tail -f(se o arquivo cresce rapidamente, pode-se descartar algumas linhas e, assim, o NR começa com o número errado), é possível pular as $llinhas? (e que limite existe para a cauda -nno posix e no gnu?). Talvez com um arquivo intermediário temporário?
precisa

@OlivierDulac, tail -n +1(leia qualquer coisa da posição inicial) aborda as preocupações das condições da corrida. Ele lerá as linhas que não estavam no arquivo no momento wc -lfinalizado, na posição exata que o wcdeixou. Portanto, a NR terá a posição correta, independentemente de quantas linhas foram escritas entre o wcfinal e o tailinício. É se você disser tailpara começar de alguma posição em relação ao final do arquivo que você terá problemas.
Stéphane Chazelas

oh, interessante: de fato, os dados se acumulam em stdin enquanto nada os lê (entre o final do wc e o início da cabeça) ... eu deveria ter percebido isso. THX. Agora eu vejo porque você "<arquivo". esperto, como de costume :) #
1119 Olivier Dulac

1
@OlivierDulac, sobre limitações (que não se aplicam tail -n +1aqui), para arquivos regulares, a maioria das implementações não tem uma, pois podem começar do final e seekvoltar até encontrar a enésima nova linha sem precisar armazenar mais de um buf de dados na memória. Para entradas não procuráveis, é aí que você pode encontrar limites. O POSIX exige implementações para poder armazenar pelo menos 10 x LINE_MAX bytes (LINE_MAX sendo pelo menos 2048). Cauda GNU não tem limite diferente de memória AFAIK
Stéphane Chazelas

0

Se você quiser numerar desde o início, precisará do grep -n para aplicar a todas as linhas.

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

Se você quisesse mostrar apenas os últimos 10, eu pensaria que você poderia refazer o arquivo:

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

O primeiro é útil, mas mostra muita saída. Não sei por que o segundo não funciona.


Cauda não tem um "mostrar todas as linhas", portanto, meu 100000000
Martin Cleaver

1
tail -n +1 -fpara seguir desde o início.
Stéphane Chazelas

1
O segundo não funciona porque o mais à direita tailnão pode produzir nada até que tenha visto a última linha de sua entrada (como saberia qual é a décima última linha?) Que nunca acontecerá como tail -fnunca para.
Stéphane Chazelas

-1

O comando cat -n [filename] | tailobterá uma contagem rápida e a exibição dos registros mais recentes, se é isso que você está procurando.

A -fopção torna persistente até a fuga - o que realmente não parece aplicável no seu cenário ou é redundante.

wc -l [filename] receberá uma contagem das linhas no alvo

wc -l [filenameprefix]* contará todas as linhas em todos os arquivos correspondentes ao padrão e até relatará um total de resumo no final.

Detalhes mais completos podem gerar respostas mais completas.


-1

É o argumento nou --lines(usado de maneiras ligeiramente diferentes, veja abaixo):

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

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

Veja também a ajuda:

$ tail --help

1
O OP quer números de linha, não um número de linhas.
robbat2 18/01
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.