Como obter estatísticas de rede em tempo real no Linux no formato KB / MB / Bytes e para porta específica ou processoID do aplicativo?

22

Eu costumava IPTraf, Iftop, vnstat, bwm-ng, ifconfig -a. Nenhum deles está me ajudando a encontrar pacotes em tempo real que estão sendo enviados / recebidos do meu aplicativo no formato KB ou MB. O motivo é que estou escrevendo um aplicativo, onde preciso ter certeza de que minha compactação está correta, mas não posso testar para avançar.

O que posso usar para rastrear estatísticas de rede em tempo real muito específicas e precisas?

insira a descrição da imagem aqui

YumYumYum
fonte

Respostas:

27

Seu aplicativo provavelmente está enviando pacotes para um número de porta UDP ou TCP específico ou para um endereço IP específico.

Portanto, você pode usar algo como TCPdump para capturar esse tráfego.

O TCPdump não fornece as estatísticas em tempo real que você deseja, mas você pode alimentá-lo com algo que funcione (tentarei atualizar esta resposta com uma resposta posteriormente).


Atualizar:

$ sudo tcpdump -i eth1 -l -e -n | ./netbps
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 96 bytes
11:36:53    2143.33 Bps
11:37:03    1995.99 Bps
11:37:13    2008.35 Bps
11:37:23    1999.97 Bps
11:37:33    2083.32 Bps
131 packets captured
131 packets received by filter
0 packets dropped by kernel

Eu o interrompi depois de um minuto pressionando Ctrl + C.

Você precisaria adicionar uma expressão de filtro adequada no final do tcpdumpcomando para incluir apenas o tráfego gerado pelo seu aplicativo (por exemplo port 123)

O programa netbpsé este:

#!/usr/bin/perl
use strict;
use warnings;
use Time::HiRes;

my $reporting_interval = 10.0; # seconds
my $bytes_this_interval = 0;
my $start_time = [Time::HiRes::gettimeofday()];

STDOUT->autoflush(1);

while (<>) {
  if (/ length (\d+):/) {
    $bytes_this_interval += $1;
    my $elapsed_seconds = Time::HiRes::tv_interval($start_time);
    if ($elapsed_seconds > $reporting_interval) {
       my $bps = $bytes_this_interval / $elapsed_seconds;
       printf "%02d:%02d:%02d %10.2f Bps\n", (localtime())[2,1,0],$bps;
       $start_time = [Time::HiRes::gettimeofday()];
       $bytes_this_interval = 0;
    }
  }
}

É apenas um exemplo, ajuste a gosto.

RedGrittyBrick
fonte
Muito obrigado, vou esperar pelo seu exemplo de trabalho. Meu objetivo era como fiz com $ bwm-ng -o plain -N -d, que mostra a saída como bit pelas interfaces, mas que falha se a interface for usada, exceto lo. Por outro lado, o IPtraf mostra excelentes bytes em tempo real. Mas não há nenhuma ferramenta que pode me dizer como bits e bytes em tempo real no RX / TX para interface específica ou qualquer interface como o total etc. eu estou perdendo isso :-(
YumYumYum
@ YumYum: resposta atualizada.
RedGrittyBrick
1
@RedGrittyBrick Você lenda absoluta! Ótimo roteiro! Muito obrigado por compartilhar. Isso responde à minha pergunta em superuser.com/questions/395226/…
Eamorr
Este deve funcionar no busybox bash em roteadores incorporados: gist.github.com/dagelf/8a842ed755354b31e79214042a4a4695
Dagelf:
Isso também é conseguido com vnstat -tr
#
14

Uso abaixo da mesma pasta:

Para verificar o empacotador por interface: ./netpps.sh eth0

Para verificar a velocidade por interface: ./netspeed.sh eth0

Medir pacotes por segundo em uma interface netpps.sh como nome do arquivo

#!/bin/bash

INTERVAL="1"  # update interval in seconds

if [ -z "$1" ]; then
        echo
        echo usage: $0 [network-interface]
        echo
        echo e.g. $0 eth0
        echo
        echo shows packets-per-second
        exit
fi

IF=$1

while true
do
        R1=`cat /sys/class/net/$1/statistics/rx_packets`
        T1=`cat /sys/class/net/$1/statistics/tx_packets`
        sleep $INTERVAL
        R2=`cat /sys/class/net/$1/statistics/rx_packets`
        T2=`cat /sys/class/net/$1/statistics/tx_packets`
        TXPPS=`expr $T2 - $T1`
        RXPPS=`expr $R2 - $R1`
        echo "TX $1: $TXPPS pkts/s RX $1: $RXPPS pkts/s"
done

Meça a largura de banda da rede em uma interface netspeed.sh como nome do arquivo

#!/bin/bash

INTERVAL="1"  # update interval in seconds

if [ -z "$1" ]; then
        echo
        echo usage: $0 [network-interface]
        echo
        echo e.g. $0 eth0
        echo
        exit
fi

IF=$1

while true
do
        R1=`cat /sys/class/net/$1/statistics/rx_bytes`
        T1=`cat /sys/class/net/$1/statistics/tx_bytes`
        sleep $INTERVAL
        R2=`cat /sys/class/net/$1/statistics/rx_bytes`
        T2=`cat /sys/class/net/$1/statistics/tx_bytes`
        TBPS=`expr $T2 - $T1`
        RBPS=`expr $R2 - $R1`
        TKBPS=`expr $TBPS / 1024`
        RKBPS=`expr $RBPS / 1024`
        echo "TX $1: $TKBPS kB/s RX $1: $RKBPS kB/s"
done

Consulte este site para obter mais informações http://xmodulo.com/measure-packets-per-second-throughput-high-speed-network-interface.html

Muthukumar Anbalagan
fonte
Essa não é uma solução viável para "porta específica ou ID do processo do aplicativo", pois fornece apenas a taxa por interface.
Mene
6

Mais fácil de usar e mais fácil de controlar a saída e redirecionar para arquivo para registro contínuo:

ifstat

Provavelmente vem com a maioria das distribuições linux e pode ser instalado com o brew no mac

samthebest
fonte
obrigado por isso. como os outros são justos com o Mac? Vou tentar instalar o ifstat e ver como vai. Mais algumas informações definitivamente teriam sido úteis.
precisa saber é
3

Eu acho que você pode usar a interface proc para obter as informações necessárias. Eu criei esse pequeno script de shell chamado rt_traf.sh:

#!/bin/bash

cat /proc/$1/net/netstat | grep 'IpExt: ' | tail -n 1 | awk '{ print $8 "\t" $9 }'

Isso imprimirá os octetos de entrada e saída separados por uma guia. Octetos multiplicados por 8 fornecerão bits / segundo e, em seguida, divididos por 10 ^ 6 fornecerão megabits / segundo. É claro que você pode adicionar isso ao script de shell para formatar a saída da maneira que desejar. Você pode chamar isso com o PID do seu aplicativo, assim, o ./rt_traf.sh <PID>que fornecerá uma leitura instantânea do seu aplicativo desde a inicialização. Para assistir estatísticas em tempo real por segundo, você pode agrupar o script shell no comando watch:

watch -n 1 ./rt_traf.sh <PID>

O -nparâmetro pode ser ajustado até décimos de segundo. Para fazer um cálculo ao longo do tempo, eu faria algo assim:

PID=<PID>; START=`./rt_traf.sh $PID`;IN_START=`echo $START | awk '{ print $1 }'`; OUT_START=`echo $START | awk '{ print $2 }'`; sleep 10; END=`./rt_traf.sh $PID`; IN_END=`echo $END | awk '{ print $1 }'`; OUT_END=`echo $END | awk '{ print $2 }'`; IN_BPS=`echo "scale=2; (($IN_START-$IN_END)/10)/8" | bc`; OUT_BPS=`echo "scale=2; (($OUT_START-$OUT_END)/10)/8" | bc`; echo "In: " $IN_BPS "Bits/second"; echo "Out: " $OUT_BPS "Bits/second"

Novamente, a matemática pode ser ajustada para o tamanho / hora que você precisa. Não é a solução mais elegante ou encolhida, mas deve funcionar em uma pitada.

d34dh0r53
fonte
3
Isto está errado. / proc / <PID> / net / netstat não contém dados por processo.
nab
Para expandir o comentário de nab: /proc/<pid>/net/netstatretorna os mesmos dados que proc/net/netstat, ie. você obtém os mesmos dados para qualquer / todos os processos.
EML
2

Eu só precisava medir a quantidade de tráfego mysql entrando e saindo em um sistema antigo em que o perl não funcionava corretamente, então não pude resistir a escrever algumas linhas de awk que atendem ao mesmo objetivo de medir o tráfego total visto pelo tcpdump:

# tcpdump -l -e -n port 3306 | \
  awk '{
  t=substr($1, 0, 8);
  n=substr($9, 0, length($9)-1);
  if(t != pt){
    print t, sum;
    sum = 0;
  } else {
    sum += n
  }
  pt=t;
}'

tcpdump: WARNING: eth0: no IPv4 address assigned
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
14:41:54 
14:41:55 466905
14:41:56 765220
14:41:57 741511
14:41:58 688219
14:41:59 492322
14:42:00 800087
14:42:01 1248608
14:42:02 1276476
14:42:03 755586
14:42:04 1029453
14:42:05 818298
^C32515 packets captured
32633 packets received by filter
107 packets dropped by kernel

E se você gosta mais de uma linha, aqui está uma para você:

tcpdump -l -e -n port 3306 | awk '{t=substr($1,0,8);n=substr($9,0,length($9)-1);if(t!=pt){print t,sum;sum=0;}else{sum+=n}pt=t;}'
Aurimas Mikalauskas
fonte
A elsedeclaração deve ser removida, caso contrário, as linhas serão ignoradas e sumnão serão precisas. tcpdump -l -e -n port 3306 | awk '{t=substr($1,0,8);n=substr($9,0,length($9)-1);if(t!=pt){print t,sum;sum=0;};sum+=n;pt=t;}
David
0

Por aplicativo pode ser feito com uma regra de firewall usando xtables e uma modificação do abaixo.

Isso não responde à pergunta "por aplicativo", mas apenas à pergunta "por interface".

Abaixo está um script que funciona na maioria dos roteadores Linux incorporados, como os compatíveis com Ubiquiti e OpenWRT, e obtém seus detalhes em / proc / net / dev.

(E fácil de mudar para pacotes etc.)

#!/bin/sh

SLP=1 # output / sleep interval
DEVICE=$1
IS_GOOD=0
for GOOD_DEVICE in `grep \: /proc/net/dev | awk -F: '{print $1}'`; do
    if [ "$DEVICE" = $GOOD_DEVICE ]; then
        IS_GOOD=1
        break
    fi
done

if [ $IS_GOOD -eq 0 ]; then
    echo "Device not found. Should be one of these:"
        grep ":" /proc/net/dev | awk -F: '{print $1}' | sed s@\ @@g 
    exit 1
fi

while true; do

LINE=`grep $1 /proc/net/dev | sed s/.*://`;
RECEIVED1=`echo $LINE | awk '{print $1}'`
TRANSMITTED1=`echo $LINE | awk '{print $9}'`
TOTAL=$(($RECEIVED1+$TRANSMITTED1))

sleep $SLP

LINE=`grep $1 /proc/net/dev | sed s/.*://`;
RECEIVED2=`echo $LINE | awk '{print $1}'`
TRANSMITTED2=`echo $LINE | awk '{print $9}'`
SPEED=$((($RECEIVED2+$TRANSMITTED2-$TOTAL)/$SLP))
INSPEED=$((($RECEIVED2-$RECEIVED1)/$SLP))
OUTSPEED=$((($TRANSMITTED2-$TRANSMITTED1)/$SLP))

printf "In: %12i KB/s | Out: %12i KB/s | Total: %12i KB/s\n" $(($INSPEED/1024)) $(($OUTSPEED/1024)) $((($INSPEED+$OUTSPEED)/1024)) ;

done;

Copie o acima para sua área de transferência e, em seguida, em uma sessão de terminal no seu roteador:

$ cat > /tmp/n.sh

então: Ctrl + V (ou clique com o botão direito do mouse / Colar)

então: Ctrl + D

$ chmod +x /tmp/n.sh

$ /tmp/n.sh eth0

Você também pode colá-lo em um bloco de notas e repita o procedimento acima se precisar editá-lo - nem todos os roteadores incorporados têm um editor! Certifique-se de copiar tudo, desde o # na parte superior até o concluído; no fundo.

O exemplo netpps acima é ótimo BTW - mas nem todos os dispositivos possuem um sistema de arquivos montado / sys. Você também pode precisar alterar o / bin / bash para / bin / sh ou vice-versa.

Fonte: https://gist.github.com/dagelf/ab2bad26ce96fa8d79b0834cd8cab549

Dagelf
fonte
Não publique a mesma resposta em várias perguntas. Se a mesma informação realmente responder a ambas as perguntas, uma pergunta (geralmente a mais recente) deve ser fechada como duplicata da outra. Você pode indicar isso votando para fechá-lo como duplicado ou, se você não tiver reputação suficiente para isso, levante uma bandeira para indicar que é uma duplicata. Caso contrário, adapte sua resposta a essa pergunta e não cole a mesma em vários lugares.
DavidPostill
Você postou exatamente o mesmo comentário no meu outro post ... que foi personalizado por acidente ... Esse tipo de resposta me faz pensar por que dediquei tempo para contribuir aqui.
Dagelf 24/05
Se foi personalizado, isso aconteceu depois que as postagens foram marcadas automaticamente pelo sistema. Não tenho tempo para ler todas as palavras para ver se são personalizadas ou não.
DavidPostill
1
A única personalização que você fez foi adicionar duas frases no início do seu anser. O restante parece idêntico. E essas duas frases não estavam na resposta original como postada - e é por isso que foi automaticamente sinalizada como resposta duplicada.
DavidPostill