Não é possível processar o stdout com o pipe quando ele chega

3

Eu estou rodando tshark em um fifo, e o seguinte é um exemplo simples de um loop que imprime a saída de tshark como vem :

tshark -i $fifo | while read line; do
    echo $line
done

O problema aparece quando eu adiciono filtros ao tshark. Este exemplo imprime todos os $line s somente após as saídas do tshark (o endereço IP está oculto):

tshark -i $fifo -T fields -e text -R '
    ip.src == **.**.***.**          &&
    http.response.code == 200       &&
    http.content_encoding == "gzip" &&
    http.content_type contains "text/html"
' | while read line; do
    echo $line
done

Eu tentei em outras formas sem sorte:

while read line; do
    echo $line
done < <(tshark ...)

while read line; do
    echo $line
done <<<"$(tshark ...)"

Mesmo o grep imprime as linhas somente depois que o tshark termina:

tshark ... | grep .

Eu tentei executar o tshark sem um cano e as linhas foram impressas corretamente conforme elas são exibidas. Por que o comando após o pipe ser alimentado somente após a saída do tshark?

Detalhes adicionais: | tee funciona, mas tudo é impresso novamente quando o tshark sai, por isso não é um bom negócio.

    
por Teresa e Junior 14.04.2013 / 23:21

3 respostas

4

Verifique se a sua versão tshark tem a opção -l para a saída (quase) com buffer de linha.

    
por 15.04.2013 / 16:21
4

Consegui que funcionasse com stdbuf do coreutils. Note que todo comando após o pipe requer que o buffer seja ajustado também:

stdbuf -o 0 tshark -i $fifo -T fields -e text -R '
    ip.src == **.**.***.**          &&
    http.response.code == 200       &&
    http.content_encoding == "gzip" &&
    http.content_type contains "text/html"
' | 
stdbuf -o 0 sed 's/\r\n,\?/\n/g; s/\t/\t/g' |

Da página do manual:

'stdbuf': Run a command with modified I/O stream buffering

(...)

'-o MODE'
'--output=MODE'
     Adjust the standard output stream buffering.
    
por 15.04.2013 / 04:17
3

Alguns utilitários chamam isatty () para determinar se a saída é um terminal e ajusta seu comportamento de acordo. gzip é um bom exemplo disso.

Tente executá-lo com script(1) :

-c, --command command

Run the command rather than an interactive shell. This makes it easy for a script to capture the output of a program that behaves differently when its stdout is not a tty.

Se você executar assim:

script -c tshark -i $fifo -T fields -e text -R '
    ip.src == **.**.***.**          &&
    http.response.code == 200       &&
    http.content_encoding == "gzip" &&
    http.content_type contains "text/html"
' | while read line; do
    echo $line
done

Você deve conseguir ver as linhas ao vivo.

    
por 15.04.2013 / 03:06