如何在Linux中以KB / MB /字节格式以及特定端口或应用程序processID获取实时网络统计信息?


22

我用IPTrafIftopvnstatbwm-ngifconfig -a。它们都没有帮助我查找从我的应用程序以KB或MB格式发送/接收的实时数据包。原因是我正在编写一个应用程序,我需要在其中确保我的压缩正确无误,但是我无法测试前进的方向。

我可以用来跟踪非常具体且准确的实时网络统计信息吗?

在此处输入图片说明

Answers:


27

您的应用程序可能正在将数据包发送到特定的UDP或TCP端口号或特定的IP地址。

因此,您可以使用类似TCPdump的功能来捕获该流量。

TCPdump不会为您提供所需的实时统计信息,但您可以将其输出提供给需要的实时统计信息(稍后,我将尝试使用答案来更新此答案)。


更新:

$ 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

一分钟后,我通过按Ctrl + C中断了它。

您需要在tcpdump命令末尾添加一个合适的过滤器表达式,以仅包括应用程序生成的流量(例如port 123

程序netbps是这样的:

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

这只是一个例子,根据口味进行调整。


非常感谢,我将等待您的工作示例。我的目标就像我对$ bwm-ng -o plain -N -d所做的一样,它按接口逐位显示输出,但是如果使用lo以外的接口则失败。另一方面,IPtraf可以实时显示出色的字节。但是没有工具可以告诉我特定接口或任何接口的RX / TX中的位和字节的实时性,我不知道它是什么:-(
YumYumYum

@YumYum:答案已更新。
RedGrittyBrick

1
@RedGrittyBrick你绝对的传奇!很棒的脚本!非常感谢分享。这回答了我在superuser.com/questions/395226/…上的
Eamorr

这应该可以在嵌入式路由器上的busybox bash中使用:gist.github.com/dagelf/8a842ed755354b31e79214042a4a4695
Dagelf

这也可以通过vnstat -tr
St0rM

14

在同一文件夹中的用法如下:

要检查每个接口的打包程序: ./netpps.sh eth0

要检查每个接口的速度: ./netspeed.sh eth0

在接口netpps.sh上每秒测量数据包数作为文件名

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

在接口netspeed.sh上测量网络带宽作为文件名

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

请参考该网站以获取更多信息http://xmodulo.com/measure-packets-per-second-throughput-high-speed-network-interface.html


对于“特定端口或应用程序processID”,这不是可行的解决方案,因为它只能为您提供每个接口的速率。
Mene

6

最易于使用和控制输出,并重定向到文件以进行连续日志记录:

ifstat

可能随大多数Linux发行版一起提供,并且可以在Mac上与brew一起安装


感谢那。其他与Mac公平吗?我将尝试安装ifstat并查看其运行方式。一些更多的信息肯定是有用的。
nyxee

3

我认为您可以使用proc界面获取所需的信息。我创建了一个名为rt_traf.sh的小外壳脚本:

#!/bin/bash

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

这将打印由标签分隔的输入和输出八位字节。八位字节乘以8将得到比特/秒,然后再除以10 ^ 6将得到兆比特/秒。当然,您可以将其添加到Shell脚本中,以设置所需格式的输出。您可以像这样使用应用程序的PID调用此函数,./rt_traf.sh <PID>这将使您自启动以来即刻读取应用程序。要查看每秒的实时统计信息,可以将shell脚本包装在watch命令中:

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

-n参数可以一直调整到十分之一秒。为了进行一段时间的计算,我将执行以下操作:

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"

同样,可以根据需要的大小/时间调整数学。不是最优雅或收缩包装的解决方案,但它应该能在紧要关头工作。


3
错了 / proc / <PID> / net / netstat不包含每个进程的数据。
2013年

为了扩展nab的注释:/proc/<pid>/net/netstat返回与相同的数据proc/net/netstat,即。对于任何/所有过程,您都会获得相同的数据。
EML

2

我只需要测量在perl无法正常工作的旧系统上进出MySQL流量的多少,因此我无法抗拒编写几行awk,以达到测量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

而且,如果您更喜欢单线飞机,那么这里有一种适合您:

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;}'

else语句应被删除,否则行将被跳过,并且sum将不准确。 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;}
大卫

0

每个应用程序都可以使用xtables和以下内容的防火墙规则来完成。

这不能回答“每个应用程序”的问题,而只能回答“每个接口”的问题。

以下是可在大多数嵌入式Linux路由器(例如Ubiquiti和OpenWRT兼容路由器)上运行的脚本,并从/ proc / net / dev获取其详细信息。

(并且易于更改为数据包等)

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

将以上内容复制到剪贴板,然后在路由器的终端会话中:

$ cat > /tmp/n.sh

然后:Ctrl + V(或右键单击/粘贴)

然后:Ctrl + D

$ chmod +x /tmp/n.sh

$ /tmp/n.sh eth0

您也可以将其粘贴在记事本中,然后在需要编辑时重复上述步骤-并非所有嵌入式路由器都具有编辑器!确保将所有内容从顶部的#复制到完成。在底部。

上面的netpps示例是很棒的BTW-但并非所有设备都具有已挂载的/ sys文件系统。您可能还必须将/ bin / bash更改为/ bin / sh,反之亦然。

资料来源:https : //gist.github.com/dagelf/ab2bad26ce96fa8d79b0834cd8cab549


请不要对多个问题发布相同的答案。如果相同的信息确实回答了两个问题,则应关闭一个问题(通常是较新的问题),作为另一个问题的重复。您可以通过投票将其关闭作为重复项来表明这一点,或者,如果您没有足够的声誉,可以举一个标志来表明它是重复项。否则,请针对这个问题量身定制答案,而不仅仅是在多个地方粘贴相同的答案。
DavidPostill

您在我的其他帖子上发表了完全相同的评论……这是偶然定制的……这种回应让我感到奇怪,为什么我花时间在这里做出贡献。
Dagelf

如果是自定义的,则在系统自动标记帖子后发生。我没有时间阅读每个单词,看看它们是否是自定义的。
DavidPostill

1
您所做的唯一定制是在分析服务的开头添加两个句子。其余似乎相同。而且这两个句子不在发布的原始答案中-这就是为什么将其自动标记为重复答案的原因。
DavidPostill
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.