How to get real-time network statistics in Linux with KB/MB/Bytes format and for specific port or application processID?

125,409

Solution 1

Your application is probably sending packets to a specific UDP or TCP port number or to a specific IP-address.

You can therefore use something like TCPdump to capture that traffic.

TCPdump doesn't give you the real-time stats you desire but you can feed it's output to something that does (I'll try to update this answer with an answer later).


Update:

$ 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

I interrupted that after a minute by pressing Ctrl+C.

You'd need to add a suitable filter expression at the end of the tcpdump command to only include the traffic generated by your app (e.g. port 123)

The program netbps is this:

#!/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;
    }
  }
}

It's just an example, adjust to taste.

Solution 2

Usage as below from same folder:

To check packer per interface: ./netpps.sh eth0

To check speed per interface: ./netspeed.sh eth0

Measure Packets per Second on an Interface netpps.sh as file name

#!/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

Measure Network Bandwidth on an Interface netspeed.sh as file name

#!/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

Please refer this site for more info http://xmodulo.com/measure-packets-per-second-throughput-high-speed-network-interface.html

Solution 3

Easiest to use and easiest to control output and redirect to file for continuous logging:

ifstat

Probably comes with most linux distributions, and can be installed with brew on mac

Solution 4

I think you can use the proc interface to get the information you need. I created this little shell script called rt_traf.sh:

#!/bin/bash

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

This will print the in and out octets separated by a tab. Octets multiplied by 8 will give you bits/second and then divided by 10^6 will give you megabits/second. Of course you can add this to the shell script to format the output how you want it. You can call this with the PID of your application like so ./rt_traf.sh <PID> which will give you an instantaneous reading of your application since startup. To watch real time stats per second you can wrap the shell script in the watch command:

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

The -n parameter can be adjusted all the way down to tenths of a second. To do a calculation over time I would do something like this:

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"

Again the math can be adjusted for the size/times you need. Not the most elegant or shrink wrapped solution but it should work in a pinch.

Solution 5

I just needed to measure how much mysql traffic is going in and out on an old system where perl didn't work properly, so I couldn't resist writing few lines of awk that serve the same goal of measuring total traffic seen by 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

And if you like one-liners better, here's one for you:

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;}'
Share:
125,409

Related videos on Youtube

YumYumYum
Author by

YumYumYum

Updated on September 18, 2022

Comments

  • YumYumYum
    YumYumYum about 1 year

    I used IPTraf, Iftop, vnstat, bwm-ng, ifconfig -a. None of them is helping me to find real-time packets that are being sent/received from my application in KB or MB format. The reason is I am writing an application, where I need to be very sure my compression is correct, but I can't test to move forward.

    What I can use to track very specific and accurate real-time network statistics?

    enter image description here

  • YumYumYum
    YumYumYum almost 12 years
    Many thanks, i will wait for your working example. My goal was like i did with $ bwm-ng -o plain -N -d which shows output as bit by interfaces but that failes if the interface is used except lo. In other hand the IPtraf shows excellent bytes realtime. But there is no tools which can tell me like bits and bytes realtime in RX/TX for specific interface or any interface as total etc. I am missing it :-(
  • user5249203
    user5249203 almost 12 years
    @YumYum: answer updated.
  • Eamorr
    Eamorr over 11 years
    @RedGrittyBrick You absolute legend! Great script! Thanks so much for sharing. This answers my question at superuser.com/questions/395226/…
  • nab
    nab about 10 years
    This is wrong. /proc/<PID>/net/netstat doesn't contain per process data.
  • Mene
    Mene about 7 years
    This is not a feasible solution for "specific port or application processID" as it only gives you the rate per interface.
  • nyxee
    nyxee over 6 years
    thanks for that. how do the others fair with Mac? I'll try to install ifstat and see how it goes. Some more info would definitely have been useful.
  • EML
    EML over 6 years
    To expand on nab's comment: /proc/<pid>/net/netstat returns the same data as proc/net/netstat, ie. you get the same data for any/all processes.
  • Dagelf
    Dagelf over 5 years
    This one should work in busybox bash on embedded routers: gist.github.com/dagelf/8a842ed755354b31e79214042a4a4695
  • DavidPostill
    DavidPostill over 5 years
    Please do not post the same answer to multiple questions. If the same information really answers both questions, then one question (usually the newer one) should be closed as a duplicate of the other. You can indicate this by voting to close it as a duplicate or, if you don't have enough reputation for that, raise a flag to indicate that it's a duplicate. Otherwise tailor your answer to this question and don't just paste the same answer in multiple places.
  • Dagelf
    Dagelf over 5 years
    You posted exactly the same comment on my other post... which was incidentally customized... This kind of response just makes me wonder why I took the time to contribute here.
  • DavidPostill
    DavidPostill over 5 years
    If it was customised then that happened after the posts were autoflagged by the system. I don't have time to read every word to see if they are customized or not.
  • DavidPostill
    DavidPostill over 5 years
    The only customization you did was to add two sentences at the start of your anser. The remainder seems identical. And those two sentences were not in the original answer as posted - which is why it was automatically flagged as a duplicate answer.
  • david
    david over 5 years
    The else statement should be removed otherwise lines will be skipped, and sum won't be accurate. tcpdump -l -e -n port 3306 | awk '{t=substr($1,0,8);n=substr($9,0,length($9)-1);if(t!=pt){pri‌​nt t,sum;sum=0;};sum+=n;pt=t;}
  • ElementalStorm
    ElementalStorm about 5 years
    This is also achieved with vnstat -tr
  • Iker Jimenez
    Iker Jimenez almost 4 years
    It doesn't appear that this tool allows to discriminate by port
  • Iker Jimenez
    Iker Jimenez almost 4 years
    @david the command in your comment is missing a closing '