通过/proc/net/dev该文件可以获取所有网卡的时时数据信息。通过/sys/class/net/下的文件同样可以获取每块网卡更详细的信息。在cnblogs博客园上看到<a href="http://www.cnblogs.com/chengmo/archive/2010/10/09/1846826.html" target="_blank" rel="noopener">程默的博客中有一篇使用awk 程序</a>精妙的搞了一个网卡实时流量监控脚本。程序虽然写的非常不错,不过统计的只是网卡向外发送的实时流量情况,我没事也搞了一个脚本,可以实时监控所有网卡的rx、tx及总的流量情况。
一、/proc/net/dev文件介绍
查看该虚拟文件得到的信息如下:
[root@361way ~]# cat /proc/net/dev|column -t Inter-| Receive | Transmit face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed lo: 30288411132 22091019 0 0 0 0 0 0 30288411132 22091019 0 0 0 0 0 0 eth0: 3368488625 73197048 0 0 0 0 0 0 288645561 966715 0 0 0 0 0 0 eth1: 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秒时可以省略。代码如下:
awk 'BEGIN{ OFMT="%.3f"; devf="/proc/net/dev"; while(("cat "devf) | getline) { if($0 ~ /:/ && ($10+0) > 0) { split($1,tarr,":"); net[tarr[1]]=$10+tarr[2]; print tarr[1],$10+tarr[2]; } } close(devf); while((system("sleep 1 ")) >=0) { system("clear"); while( getline < devf ) { if($0 ~ /:/ && ($10+0) > 0) { split($1,tarr,":"); if(tarr[1] in net) { print tarr[1],":",($10+tarr[2]-net[tarr[1]])*8/1024,"kb/s"; net[tarr[1]]=$10+tarr[2]; } } } close(devf); } }'
说明:第一个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两个文件,代码如下:
#/bin/bash # site: www.361way.com # mail: itybku@139.com # Get all interface network flow ,refresh by 2 second define inet_byte() { for i in `ls /sys/class/net/`; do let "$i"_rx"$1"=`cat /sys/class/net/$i/statistics/rx_bytes` let "$i"_tx"$1"=`cat /sys/class/net/$i/statistics/tx_bytes` #eval echo '$'"$i"_rx"$1" done } eva() { a1=`eval echo '$'"$1"_rx1` a2=`eval echo '$'"$1"_rx2` b1=`eval echo '$'"$1"_tx1` b2=`eval echo '$'"$1"_tx2` tol1=$(($a1+$b1)) tol2=$(($a2+$b2)) #echo $1 $a1 $a2 $b1 $b2 $tol1 $tol2 rxkB=$(echo $a2 $a1 | awk '{ printf "%0.2f" ,($1-$2)/1024 }') txkB=$(echo $b2 $b1 | awk '{ printf "%0.2f" ,($1-$2)/1024 }') TolkB=$(echo $tol2 $tol1 | awk '{ printf "%0.2f" ,($1-$2)/1024 }') echo -e "$1\t\t$rxkB\t$txkB\t$TolkB" } while true; do sleep 2 clear awk 'BEGIN {print "interface\trxKB\ttxKB\tTotalKB\n==========================================";}' inet_byte 1 sleep 1 inet_byte 2 for i in `ls /sys/class/net/`; do eva $i #echo $i $a1 $a2 $b1 $b2 $tol1 $tol2 #echo "$i $a $b $c" done done
两个脚本的效果对比如下图:
<img alt="" src="https://www.361way.com/wp-content/uploads/2013/01/awk-network.png" width="570" height="78" />
左边为awk脚本执行的效果,右边为我写的小脚本运行的效果。还需要注意的是在awk程序中将Byte 通过乘8转化为bit ,所以最终显示的是kb,而我脚本现实的是kB,两者同时统计的话是差8倍的。