Contar linhas de entrada sem terminação

5

Existe alguma maneira de contar as linhas de uma fonte de entrada sem terminação? Por exemplo, quero executar o seguinte por um período de tempo para contar o número de solicitações:

ngrep -W byline port 80 and dst host 1.2.3.4 | grep ":80" | wc

Obviamente, isso não funciona. Quando eu Ctrl + C mata isso, eu não vou obter nenhuma saída de wc . Eu preferiria evitar criar um arquivo, se puder.

    
por blurryrunner 03.09.2014 / 19:37

4 respostas

4

Digitar Ctrl + C do terminal envia SIGINT para o grupo de processos em primeiro plano. Se você quiser que wc sobreviva a este evento e produza saída, você precisa ignorar o sinal.

A solução é executar wc em um subshell e ter seu shell shell definido como SIGINT a ser ignorado antes de executar wc . wc herdará essa configuração e não morrerá quando SIGINT for enviado para o grupo de processos. O restante do pipeline vai morrer, deixando wc lendo de um pipe que não tem processo no outro extremo. Isso fará com que wc veja EOF no canal e, em seguida, exibirá suas contagens e sairá.

ngrep -W byline port 80 and dst host 1.2.3.4 | grep ":80" | (trap '' INT ; wc)
    
por 03.09.2014 / 19:50
2

Veja como você pode continuar contando depois de ler a contagem atual:

Minha fonte de entrada de teste sem terminação é um ping:

$ ping 127.0.0.1  
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.041 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.028 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.025 ms
64 bytes from 127.0.0.1: icmp_seq=4 ttl=64 time=0.045 ms
64 bytes from 127.0.0.1: icmp_seq=5 ttl=64 time=0.032 ms
64 bytes from 127.0.0.1: icmp_seq=6 ttl=64 time=0.030 ms
^C

Com outras soluções, tivemos que decidir quando ler a contagem de linhas e interromper o comando em execução.
Mas, idealmente, gostaríamos apenas de saber a contagem atual de linhas, certo?

Então, por que não contar apenas as linhas? A ferramenta certa para o trabalho é nl , adicionando a contagem atual na frente de cada linha:

$ ping 127.0.0.1 | nl
     1  PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
     2  64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.040 ms
     3  64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.022 ms
     4  64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.025 ms
     5  64 bytes from 127.0.0.1: icmp_seq=4 ttl=64 time=0.021 ms
     6  64 bytes from 127.0.0.1: icmp_seq=5 ttl=64 time=0.022 ms
     7  64 bytes from 127.0.0.1: icmp_seq=6 ttl=64 time=0.022 ms
     8  64 bytes from 127.0.0.1: icmp_seq=7 ttl=64 time=0.021 ms
     9  64 bytes from 127.0.0.1: icmp_seq=8 ttl=64 time=0.029 ms
^C
    
por 03.09.2014 / 23:23
0

Você pode usar:

$ ngrep -W byline port 80 and dst host 1.2.3.4 | grep ":80" |
perl -nle 'system("clear");print $.'

perl acompanhará as linhas que você tinha, limpe a saída antiga antes de imprimi-la.

    
por 03.09.2014 / 19:57
0

Se você estiver disposto a especificar um limite de tempo (em vez de apenas eliminá-lo), você poderia usar esse truque

( cmdpid=$BASHPID; (sleep 300; kill $cmdpid) & exec ngrep (ngrep args) ) | grep ":80" | wc

inspirado por esta resposta a uma pergunta recente mais de SU; essencialmente Como parar um programa em execução após 5 minutos e continuar?

    
por 03.09.2014 / 20:53

Tags