script tail-pipe-awk, bem no Centos, mas estranho no Ubuntu

1

Eu escrevi um script no CentOS e agora estou tentando executá-lo no Ubuntu e ele está se comportando de forma inesperada. Aqui está algo como o script, que eu corro sob bash:

sudo tail -F /var/opt/my-application/log/my-application.log |
awk '
BEGIN {
    ORS=" "
}
{ if ($8 ~ /MATCH-TEXT/) {
            # do a whole bunch of stuff here
            # like look in /proc and calculate CPU and interface stats
    };
 };
} '

Anteriormente, quando uma linha com MATCH-TEXT aparecia no campo $ 8 do meu log, todas as "fazem um monte de coisas" (a carne do script) aconteciam e eu via a saída. Meu aplicativo gera linhas MATCH-TEXT uma vez por segundo (às vezes mais, às vezes menos) e o mesmo acontece com a saída desse script.

Agora, no entanto, quando inicio este script, não obtenho nenhuma saída por um longo tempo e, então, recebo talvez 30 linhas de saída de uma só vez. Parece que o script está enfileirando as linhas de log recebidas e, em seguida, executando várias vezes rapidamente, porque os cálculos na CPU e na interface são adequados para "desde uma pequena fração de segundo", em vez de "desde um segundo atrás". / p>

Ainda mais estranho é que comentar toda a carne do comando awk para substituí-la por uma "print $ 0" (transformando todo o script em um comando desajeitado grep) produz o mesmo resultado. Então, estou confiante de que é a maneira como o sistema está executando esse script e não algo no próprio script.

Enquanto isso, em outra janela, um simples "sudo tail -F my-application.log | grep MATCH-TEXT" obtém a saída a cada segundo (como esperado).

Alguma idéia do que está acontecendo aqui? Alguma dica de onde devo começar a procurar o que está causando esse comportamento de enfileiramento?

    
por jg3 24.04.2013 / 21:55

3 respostas

0

Depois de pesquisar todas as respostas e tentar fflush e stdbuf (que eu não sabia anteriormente, obrigado), descobri que a resposta está em duas partes:

1) O CentOS usa o gawk, o Ubuntu usa o mawk (por padrão).

I have no comment on which is better or why the decision to use either has been made, differences are what make the two distributions different. (:

2) mawk tem uma opção de linha de comando para "interativo", a partir da página de manual:

 -W interactive

 sets unbuffered writes to stdout and line buffered reads from stdin.
 Records from stdin are lines regardless of the value of RS.

Eu só posso supor que é porque o buffer estava dentro do awk e não no próprio script que faz este trabalho onde o stdbuf não funcionou.

    
por 25.04.2013 / 16:23
1

Se isto não é devido a uma diferença em tail , então eu concordo com Hauke Laging que é provavelmente um problema de buffering. Para liberar o buffer de saída de awk , tente adicionar fflush() após suas instruções de impressão, como fiz no código de teste a seguir:

tail -F /var/log/apache2/access_log | awk '{ if ($8 ~ /MATCH-TEXT/) { print $0; fflush(); }}'
    
por 24.04.2013 / 22:56
0

mawk -W interactive corrigiu meu problema no Debian Wheezy.

    tail -f data.log | grep --line-buffered '$DataString' | mawk -W interactive -F "," '{print "var2", $2, "var4", $4}'
    
por 14.11.2013 / 10:06