前言

本文会是一个系列,每次介绍一个对运维人员较为实用的shell脚本。

实现功能

获取网卡的实时流量。(本脚本在centos6.9/7.5下实测通过)

实现思路

分别获取网卡上行和下行数据

网卡流量数据信息可以使用ip -s link命令获取,但现在的主机很可能有多张网卡,比如做了bonding(端口绑定)的网卡,其真实数据在一张虚拟网卡上,所以我们的第一步工作是确认真实的数据在哪一张网卡上。

1.1 获取有真实数据的网卡。

通过 ip route命令,会以行方式显示系统路由表,并且每一行都会有某条路由对应的网卡名。其中默认路由有一个关键字default,类似如下:

[root@badteacher ~]# ip routedefault via 172.27.0.1 dev eth0 169.254.0.0/16 dev eth0 scope link metric 1002 172.27.0.0/20 dev eth0 proto kernel scope link src 172.27.0.14

我们想要的数据是default行的网卡的名称eth0,观察此行,发现内容以空格分开,分为5列,我们要的网卡名在第5列。

ip route | grep default | awk -F ' ' {'print $5'}

1.2 获取对应网卡的上下行数据

[root@badteacher ~]# ip -s link ls eth02: eth0: mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000 link/ether 52:54:00:08:16:20 brd ff:ff:ff:ff:ff:ff RX: bytes packets errors dropped overrun mcast 6415699597 70767349 0 0 0 0 TX: bytes packets errors dropped carrier collsns 10116704013 69881567 0

执行ip -s link ls eth0命令,我们想要的数据出现了,现在想办法提取出来。

通过观察,发现上行数据(Rx)固定出现在倒数第三行的第1列。

ip -s link ls $cardName | tail -n 3 | head -n 1 | awk {'print $1'}

tail -n 3取出倒数3行,head -n 1取出第1行,awk {'print $1'},输出第1列内容。这样就得到了上行数据。下行数据方法类似,只是下行数据(Tx)的数据出现在倒数第一行。

ip -s link ls $cardName | tail -n 1 | awk {'print $1'}

现在获取的数据是网卡已接收/发送的总字节数,是不能直接计算的。我们需要的数据是每秒网卡上下行流量。根据命令的特性,我们需要隔1秒再次采集网卡的上下行流量。

sleep 1

这个命令是让shell睡眠一秒(不做任何动作),然后再次获取网卡的上/下行流量,将当前获取的上/下行流量数据减去之前获取的上/下行数据,就得到了真实的流量数据。

realRxBytes=$(((curRxBytes - prevRxBytes) / 1024 / 1024 ))

因为单位是bytes,本例想以Mbytes为单位,需要除以2次1024。

2. 呈现数据

echo in:${realRxBytes}M echo out:${realTxBytes}M

脚本代码

#!/bin/bash#定义了一个名为getBytes的函数getBytes() {#此条命令的目的是获取承载系统默认路由的网卡名称。cardName=$(ip route | grep default | awk -F ' ' {'print $5'})#获取当前系统已接收的字节数prevRxBytes=$(ip -s link ls $cardName | tail -n 3 | head -n 1 | awk {'print $1'})#获取当前系统已发送的字节数prevTxBytes=$(ip -s link ls $cardName | tail -n 1 | awk {'print $1'})#让shell睡眠1秒sleep 1#再次获取当前系统已接收的字节数curRxBytes=$(ip -s link ls $cardName | tail -n 3 | head -n 1 | awk {'print $1'})#获取实际上行(in)流量,公式为当前已接收字节数-1秒前已接收字节数,得到的数字以字节为单位,#除以1次1024后单位为Kbytes,再除以1次1024后单位为Mbytes。realRxBytes=$(((curRxBytes - prevRxBytes) / 1024 / 1024 ))#再次获取当前系统已发送的字节数curTxBytes=$(ip -s link ls $cardName | tail -n 1 | awk {'print $1'})#获取实际下行(out)流量,公式和上行流量类似realTxBytes=$(((curTxBytes - prevTxBytes) / 1024 / 1024))#向屏幕输出结果echo in:${realRxBytes}Mecho out:${realTxBytes}M}#让shell支持参数,t表示用户如果在命令行下使用了参数t,例如:./test.sh -t,会将这个参数以$ARGS的方式传递给shell。while getopts t ARGSdo#通过case来为不同参数执行不同功能case $ARGS in#如果用户输入的参数为t,执行里面的代码t)#开始一个“死循环”while [ 1 ]do#调用getBytes函数getBytesdone##表示语句结束;;#case结束标志esacdone#如果执行shell时未选择参数,执行此命令getBytes

shell脚本是Linux运维人员必需掌握的武器,有了它,能让我们的运维效率有显著的提高,借此,希望我们一起学习并分享经验,共同进步。

如果你对讲解的shell有疑问,请通过评论告诉我,我会尽可能快的回复。笔者的水平也有限,如果你发现什么bug,也请告诉我,我会尽快改正。

查看原文 >>
相关文章