通过/proc/net/dev该文件可以获取所有网卡的时时数据信息。通过/sys/class/net/下的文件同样可以获取每块网卡更详细的信息。在cnblogs博客园上看到程默的博客中有一篇使用awk 程序精妙的搞了一个网卡实时流量监控脚本。程序虽然写的非常不错,不过统计的只是网卡向外发送的实时流量情况,我没事也搞了一个脚本,可以实时监控所有网卡的rx、tx及总的流量情况。

一、/proc/net/dev文件介绍

查看该虚拟文件得到的信息如下:

1[root@361way ~]# cat /proc/net/dev|column -t
2Inter-|  Receive      |          Transmit
3face     |bytes       packets    errs      drop  fifo  frame  compressed  multicast|bytes  packets      errs      drop  fifo  colls  carrier  compressed
4lo:      30288411132  22091019   0         0     0     0      0           0                30288411132  22091019  0     0     0      0        0           0
5eth0:    3368488625   73197048   0         0     0     0      0           0                288645561    966715    0     0     0      0        0           0
6eth1:    25761486247  500606223  0         0     0     0      0           0                22767379359  20753517  0     0     0      0        0           0

其中receive是收包的信息,transimit是发包的信息。我们平时关注的几个参数意思如下:

  • bytes表示收发的字节数;
  • packets表示收发正确的包量;
  • errs表示收发错误的包量;
  • drop表示收发丢弃的包量;

注:/proc/net 目录下还有一些其他文件,都是和网络相关的。

二、awk 实时流量统计

该awk脚本正是调用了/proc/net/dev中的数据,其原理是每隔一段时间再取一下值 ,再和之前的值求差,再除间隔时间段,公式可以表示式(x2 -x1 )/t ,当t间隔为1秒时可以省略。代码如下:

 1awk 'BEGIN{
 2OFMT="%.3f";
 3devf="/proc/net/dev";
 4while(("cat "devf) | getline)
 5{
 6    if($0 ~ /:/ && ($10+0) > 0)
 7    {
 8        split($1,tarr,":");
 9        net[tarr[1]]=$10+tarr[2];
10        print tarr[1],$10+tarr[2];
11    }
12}
13close(devf);
14while((system("sleep 1 ")) >=0)
15{
16    system("clear");
17    while( getline < devf )
18    {
19        if($0 ~ /:/ && ($10+0) > 0)
20            {
21                split($1,tarr,":");
22                if(tarr[1] in net)
23                {
24                    print tarr[1],":",($10+tarr[2]-net[tarr[1]])*8/1024,"kb/s";
25                    net[tarr[1]]=$10+tarr[2];
26                }
27            }
28    }
29    close(devf);
30}
31}'

说明:第一个while 是获得总的初始值,$1是网卡出流量,$10是网卡进流量。第2个while会间隔1秒钟启动一次。计算总流量差得到平均每秒流量。

注意:通过getline 逐行读取文件,需要close关闭 。否则在第2次while循环中不能获得数据。

awk这个脚本退出时只能通过ctrl + z 进行退出。

三、我的实时监控脚本

为避免落了俗套,有抄袭之嫌,我选取了从/sys/class/net相对应的接口中取值。/sys/class/net/ethX/statistics中详细每项对应的文件,由于只取流量信息,所以主要关注tx_bytes、rx_bytes两个文件,代码如下:

 1#/bin/bash
 2# site: www.361way.com
 3# mail: itybku@139.com
 4# Get all interface network flow ,refresh by 2 second define
 5inet_byte() {
 6    for i in `ls /sys/class/net/`; do
 7        let "$i"_rx"$1"=`cat /sys/class/net/$i/statistics/rx_bytes`
 8        let "$i"_tx"$1"=`cat /sys/class/net/$i/statistics/tx_bytes`
 9        #eval echo '$'"$i"_rx"$1"
10    done
11}
12eva() {
13    a1=`eval echo '$'"$1"_rx1`
14    a2=`eval echo '$'"$1"_rx2`
15    b1=`eval echo '$'"$1"_tx1`
16    b2=`eval echo '$'"$1"_tx2`
17    tol1=$(($a1+$b1))
18    tol2=$(($a2+$b2))
19    #echo $1 $a1 $a2 $b1 $b2 $tol1 $tol2
20    rxkB=$(echo $a2 $a1 | awk '{ printf "%0.2f" ,($1-$2)/1024 }')
21    txkB=$(echo $b2 $b1 | awk '{ printf "%0.2f" ,($1-$2)/1024 }')
22    TolkB=$(echo $tol2 $tol1 | awk '{ printf "%0.2f" ,($1-$2)/1024 }')
23    echo -e "$1\t\t$rxkB\t$txkB\t$TolkB"
24}
25while true; do
26    sleep 2
27    clear
28    awk 'BEGIN {print "interface\trxKB\ttxKB\tTotalKB\n==========================================";}'
29    inet_byte 1
30    sleep 1
31    inet_byte 2
32    for i in `ls /sys/class/net/`; do
33        eva $i
34        #echo $i $a1 $a2 $b1 $b2 $tol1 $tol2
35        #echo  "$i $a $b $c"
36    done
37done

两个脚本的效果对比如下图:

左边为awk脚本执行的效果,右边为我写的小脚本运行的效果。还需要注意的是在awk程序中将Byte 通过乘8转化为bit ,所以最终显示的是kb,而我脚本现实的是kB,两者同时统计的话是差8倍的。