analisar arquivo de log com saída pesada

1

Gostaria de monitorar meus logs do vsftpd e obter informações dos logs para processar os arquivos que foram enviados. Até agora tudo foi ótimo e funcionou bem:

tail -n0 -F /var/log/vsftpd.log | while read line; do
    if echo "$line" | grep -q 'OK UPLOAD:'; then
        #do a bunch of processing stuff - this takes some time
    fi
done

Comecei a fazer alguns testes em escala e enviei 500 arquivos de uma só vez. Por alguma razão, as linhas de registro estão faltando ou elas são cortadas quando você faz upload de muitas coisas. Por exemplo, uma linha típica se parece com:

Sun Apr 7 09:08:51 2013 [pid 25409] [cam02430] OK UPLOAD: Client "206.132.183.201", "/20130407/09/20130407_090842D.avi", 531792 bytes, 426.14Kbyte/sec

Mas às vezes a linha fica assim (se não estiver ausente):

:08:51 2013 [pid 25409] [cam02430] OK UPLOAD: Client "206.132.183.201", "/20130407/09/20130407_090842D.avi", 531792 bytes, 426.14Kbyte/sec

Ele está cortando os primeiros caracteres do log. Não faz isso para todas as linhas, mas sim para a maioria. Também muitas linhas estão faltando. Eu acho que tenho uma condição de corrida do meu processamento não terminar a tempo. Como posso contornar isso?

EDITAR Eu acho que tenho 3 opções:

  1. Não use a cauda e tente usar uma combinação de coisas como um cron job / grep para verificar o log de uma nova entrada. Eu imagino que isso possa ser complicado. Como faço para saber o que há de novo nesse log?

  2. Monitore a alteração do arquivo com monit ou equivalente. Eu não acredito que isso seja uma opção. Os arquivos são armazenados em diretórios um pouco aleatórios com nomes de arquivos que são marcados com hora.

  3. logstash ou equivalente. Eu não acho que esses programas atendam às minhas necessidades. Mas talvez alguém saiba o contrário.

Agora estou me concentrando no # 1 sem bons leads. Então, qualquer pensamento sobre isso seria apreciado.

    
por Tom 12.04.2013 / 21:11

4 respostas

1

Você pode começar a evitar a bifurcação de um processo "grep" para todas as linhas do log, reescrevendo seu código da seguinte forma:

tail -n0 -F /var/log/vsftpd.log | grep 'OK UPLOAD:' | while read line ; do
        #do a bunch of processing stuff - this takes some time
done

Mas eu concordo com outros pôsteres, o shell não é realmente adequado para manipulação pesada de texto / string. Você deve considerar o uso de outro mecanismo de script (pelo menos awk, ou melhor perl ou python)

    
por 16.04.2013 / 16:18
1

Eu tive uma boa experiência com o Perl usando o arquivo aberto '<' opções, se você estiver disposto a relaxar apenas o seu limite para scripts de shell.

por exemplo. link

    
por 18.04.2013 / 18:34
1

Como o @epoon sugerido , o Perl pode ser uma boa escolha:

#!/usr/bin/env perl

open(FH,'<',$ARGV[0]) || die("Could not open file $ARGV[0]\n");
for (;;) {
    while (<FH>) {
    if (/OK UPLOAD/) { ## this is where you do your processing. As an example, 
                       ## I am collecting the file's info
        /^(.+?)\s*\[pid\s*(\d+).+?\"([\d\.]+).+?\"(.+?)\".+?(\d+).+?\s([^\s]+)/;
        my ($date,$pid,$client,$filename,$size,$rate) = ($1,$2,$3,$4,$5,$6);
        print "On $date, process $pid uploaded file \"$filename\" of $size bytes from $client at $rate\n"

    }
    }
    # eof reached on FH, but wait a second and maybe there will be more output
    sleep 1;
    seek FH, 0, 1;      # this clears the eof flag on FH
}

A execução deste script em /var/log/vsftpd.log deve fornecer resultados como

On Sat Apr 20 16:30:05 CEST 2013, process 25409 uploaded file "/20130407/09/20130407_090842D.avi" of 531792 bytes from 206.132.183.201 at 426.14Kbyte/sec

Eu ficaria feliz em atualizar isso se você especificar exatamente o que deseja fazer com as informações de registro.

    
por 20.04.2013 / 16:31
0

Você tentou usar a opção --line-buffered para grep ?

tail -f /var/log/vsftpd.log | grep --line-buffered 'OK UPLOAD:' | while read line ; do
        #do a bunch of processing stuff - this takes some time
done
    
por 18.04.2013 / 16:59