Tail -f o arquivo de log mais recente

5

Em alguns pontos, consegui que isso funcionasse

ls -rt /path/to/log/file/ | tail -1 | xargs tail -f

Mas não consigo entender por que nem sempre funciona. (Isso é uma correção rápida até que eu consiga o log rolando fixo aqui)

    
por John 22.07.2013 / 15:02

4 respostas

11

Ordena o comando e o arquivo de log mais recente

Por que usar -r (ordem inversa de classificação) do que atingir o final da saída com tail ?

Usar a ordem normal de classificação e obter a primeira entrada seria mais rápido!

tail -f '/bin/ls -1td /path/to/log/file/*| /usr/bin/head -n1'

ou

tail -f $(/bin/ls -1t /path/to/log/file/* | /bin/sed q)

funcione bem.

Nota: Eu gosto de usar sed porque este comando está presente em /bin , talvez antes que /usr seja montado.

tail -f '/bin/ls -1tr /path/to/log/file/* | /bin/sed -ne '$p''

funcionaria mas, como já foi dito: inverter a ordem de classificação, do que eliminar toda a saída para usar apenas a última entrada não é uma boa ideia ; -)

Aviso , no último diretório, * não precisa corresponder a um diretório, senão o comando tail não saberá como abri-lo.

O mesmo, mas usando find para pesquisar pelo arquivo mais recente:

read -a file < <(
    find /tmp 2>/dev/null -type f -mmin +-1 -mmin -10 -printf "%Ts %p\n" |
    sort -rn)
tail -f ${file[1]}

Nota:

  • o -mmin +-1 garante a não listagem de arquivos com tempo incorreto: no futuro .
  • read está embutido, crie uma matriz e evite o uso de head -n1| cut -d \ -f2
  • -mmin -10 pode ser alterado ou suprimido, mas isso evita longos processos de classificação.

Mas suporte de acompanhamento para assistir a mais de um arquivo:

Tente abrir dois consoles do shell e tente isto:

No primeiro console:

user@host[pts/1]:~$ touch /tmp/file_{1,2,3}
user@host[pts/1]:~$ tail -f /tmp/file_{1,2,3}
==> /tmp/file_1 <==

==> /tmp/file_2 <==

==> /tmp/file_3 <==

no segundo, mantendo o 1º console visível, bateu muito tempo:

user@host[pts/2]:~$ tee -a /tmp/file_$((RANDOM%3+1)) <<<$RANDOM
25285
user@host[pts/2]:~$ tee -a /tmp/file_$((RANDOM%3+1)) <<<$RANDOM
16381
user@host[pts/2]:~$ tee -a /tmp/file_$((RANDOM%3+1)) <<<$RANDOM
19766
user@host[pts/2]:~$ tee -a /tmp/file_$((RANDOM%3+1)) <<<$RANDOM
3053

1ª consola poderia ser semelhante:

==> /tmp/file_2 <==
25285

==> /tmp/file_1 <==
16381
19766

==> /tmp/file_3 <==
3053

...

Na ideia da pergunta SO, mas baseada em tempo, multi arquivos

Usando o comando find , poderíamos assistir nos arquivos modificados dos últimos minutos -mmin ou nos últimos dias -mtime :

find /path/to/logdir -type f -mmin -10 -exec tail -f {} +

para ver arquivos de registro modificados nos últimos 10 minutos.

Nota:

  • Dê uma olhada em man tail , sobre
    • -F opção para longo tempo assistir
    • -q opção para não imprimir nomes de arquivos

Formatação de fantasia

find /path/to/logdir -type f -mmin -10 -exec tail -f {} + |
    sed -une 's/^==> .path.to.logdir.\(.*\) <==$/             /;ta;bb;
               :a;s/^\(.\{12\}\) *$/: /;h;bc;
               :b;G;s/^\(..*\)\n\(.*\)/ /p;:c;'

Onde você pode modificar .path.to.logdir. e alterar 12 para um tamanho mais adequado.

Por exemplo, mantendo nossos dois consoles, pare primeiro e tente

user@host[pts/1]:~$ find /tmp/ -type f -mtime -1 -name 'file_?' -exec tail -f {} + |
    sed -une 's/^==> .tmp.\(.*\) <==$/             /;ta;bb;
        :a;s/^\(.\{12\}\) *$/: /;h;bc;
        :b;G;s/^\(..*\)\n\(.*\)/ /p;:c;'
file_2      :  25285
file_1      :  16381
file_1      :  19766
file_3      :  3053

do que no segundo console, clique novamente em

user@host[pts/2]:~$ tee -a /tmp/file_$((RANDOM%3+1)) <<<$RANDOM
    
por 22.07.2013 / 16:39
3

Isso não funcionará a menos que você esteja em /path/to/log/file , porque ls fornece apenas o nome do arquivo e tail -f não o encontrará. Se você colocar um * no final do ls , ele fornecerá caminhos completos:

ls -rt /var/log/apache2/* | tail -1 | xargs tail -f
    
por 22.07.2013 / 15:38
1

A solução mais fácil é usar o zsh e aproveitar os qualificadores de glob om para classificar por hora de modificação (mais recente primeiro) e [1] para reter apenas a primeira correspondência.

tail -f /path/to/log/directory/*(om[1])

Se você não tiver zsh, instale-o. Se você realmente não deseja instalar o zsh, não é muito ruim usar o ls , desde que os nomes dos arquivos não contenham caracteres especiais (qualquer coisa não imprimível está causando problemas aqui), o que deve ser bom para arquivos de log. Observe que como Paylo Almeida já comentou Não é possível usar a saída de ls /path/to/log/directory , já que exibe caminhos relativos a /path/to/log/directory . Você pode mudar para esse diretório primeiro:

cd /path/to/log/directory
tail -f "$(ls -t | head -n 1)"

Ou você pode adicionar o caminho:

tail -f "/path/to/log/directory/$(ls -t /path/to/log/directory | head -n 1)"

Ou você pode obter ls para imprimir caminhos completos:

tail -f "$(ls -t /path/to/log/directory/* | head -n 1)"

O comando tail continuará seguindo o mesmo arquivo para sempre, mesmo que um arquivo de log mais recente seja criado posteriormente. Se você quiser alternar automaticamente para um arquivo diferente, precisará de uma abordagem mais sofisticada, em que detecte novos arquivos e inicie uma nova instância de tail no novo arquivo. No Linux, você pode usar a interface inotify .

while true; do
  tail -n +1 -f /path/to/log/directory/*(om[1])
  inotifywait -qq -e create /path/to/log/directory
  kill $!
done
    
por 23.07.2013 / 03:15
-1

Vá para o diretório de logs de eventos e forneça tail -f * para visualizar todos os registros recentes.

    
por 23.07.2013 / 01:28

Tags