Arquivo de log de cauda em várias máquinas sobre ssh

37

Estou tentando tailum arquivo de log em várias máquinas remotas e encaminhar a saída para minha estação de trabalho local. Quero que as conexões fechem ao pressionar Ctrl- C.

No momento, tenho a seguinte função que quase funciona como pretendido.

function dogfight_tail() {
 logfile=/var/log/server.log
 pids=""
 for box in 02 03; do
   ssh server-$box tail -f $logfile | grep $1 &
   pids="$pids $!"
 done
 trap 'kill -9 $pids' SIGINT
 trap  wait
}

As conexões fecham e eu recebo a saída de tail. MAS, há algum tipo de buffer em andamento porque a saída ocorre em lotes.

E aqui está a parte divertida…

Eu posso ver o mesmo comportamento de buffer ao executar o seguinte e anexar "teste" ao arquivo /var/log/server.lognas máquinas remotas 4-5 vezes ...

ssh server-01 "tail -f /var/log/server.log | grep test"

... e encontrou duas maneiras de desativá-lo ...

  1. Adicione sinalizador -t ao ssh.

    ssh -t server-01 "tail -f /var/log/server.log | grep test"
  2. Remova a cotação do comando remoto.

    ssh server-01 tail -f /var/log/server.log | grep test

No entanto, nenhuma dessas abordagens funciona para a função executada em várias máquinas mencionadas acima.

Eu tentei o dsh, que tem o mesmo comportamento de buffer ao executar.

dsh -m server-01,server-02 -c "tail -f /var/log/server.log | grep test"

Mesmo aqui, se eu remover a cotação, o buffer desaparece e tudo funciona bem.

dsh -m server-01,server-02 -c tail -f /var/log/server.log | grep test

Também tentei, parallel-sshque funciona exatamente da mesma forma que dsh. Alguém pode explicar o que está acontecendo aqui?

Como corrijo esse problema? Seria ideal para ir direto, sshse possível.

PS: Não quero usar nada multitailparecido, pois quero poder executar comandos arbitrários.

deephacks
fonte
Você pode fazer o checkout dbitaile fazer o download aqui .

Respostas:

36

O que você vê é o efeito de um buffer stdout padrão grepfornecido pelo Glibc. A melhor solução é desabilitá-lo usando --line-buffered(GNU grep, não sei ao certo o que outras implementações podem oferecer suporte ou algo semelhante).

Por que isso acontece apenas em alguns casos:

ssh server "tail -f /var/log/server.log | grep test"

executa o comando inteiro entre aspas no servidor - assim, grepespera para preencher seu buffer.

ssh server tail -f /var/log/server.log | grep test

é executado grepem sua máquina local na saída tailenviada pelo canal ssh.

A parte principal aqui é que grepajusta seu comportamento, dependendo se stdiné um terminal ou não. Quando você executa ssh -t, o comando remoto está sendo executado com um terminal de controle e, portanto, o remoto grepse comporta como o seu local.

peterph
fonte
Muito obrigado pela explicação detalhada. Faz sentido para mim agora e o script funciona conforme o esperado com --line-buffered.
deephacks
@deephacks Nesse caso, considere aceitar a resposta - isso dá uma pista para outras pessoas com o mesmo problema.
Peterph #
1
O buffer do grep / glibc depende de seu stdout . ssh tail | grepsaídas para o terminal local, sem buffer. ssh -t "tail|grep"produz para um pty, sem buffer. ssh "tail|grep"saídas para um tubo (para sshd), armazenado em buffer (a menos que --line-buffered).
dave_thompson_085
2

Veja isso: multitail

O MultiTail permite monitorar arquivos de log e comandar a saída em várias janelas em um terminal, colorir, filtrar e mesclar.

Para ajustar logs em vários servidores, use:

multitail -l 'ssh user@host1 "tail -f /path/to/log/file"' -l 'ssh user@host2 "tail -f /path/to/log/file"'
LeoChu
fonte
3
Mas isso não permite que você faça sobre ssh, que é uma condição dessa pergunta. (E, também, a pergunta diz especificamente "não quero usar multitail".)
bispo
1
@ Bispo: Eu acho que essa crítica é injusta em parte porque, embora a questão possa ter especificado não usar multitail, parece ser devido a um mal-entendido. O exemplo acima mostra como usar comandos arbitrários e as expansões regulares do shell também funcionam - multitail <(ssh …) <(ssh …)- permitindo o resultado desejado, mesmo que não seja o que eles pensavam originalmente que a pergunta poderia ser respondida.
Chris Adams
0

Você pode fazer o checkout no log lateral.

Uma ferramenta Java que criei, capaz de ler arquivos de log locais e distantes usando SSH. É bastante simples de usar.

Mais algumas explicações: https://github.com/pschweitz/insidelog/wiki

Basta baixar a versão correspondente ao seu sistema operacional, da versão nativa do jar executável no Java Runtime (requer java 8_40 ou superior):

https://github.com/pschweitz/insidelog/releases

Você pode encontrar uma documentação completa (incorporada na e na página do Github)

Philippe Schweitzer
fonte