本文是 Unix/Linux 系统管理自动化系列中的一篇,主要讲述如何实现自动化监控网络接口带宽状态并及时通知系统管理员采取相应措施。
在 Unix/Linux 系统的日常管理工作中,系统管理员可能会遇到因网络接口带宽耗尽而导致网络服务响应过慢,或者服务中断等问题。这些问题较严重的影响了工作效率。因此,关注系统的网络接口使用情况,建立一个警告系统对网络接口带宽的潜在问题发出警告,确保网络接口带宽没有被塞满是系统管理的一个重要的方面。
在本文中,作者介绍了一些查看网络接口使用情况的工具命令并结合这些工具实现了一个自动化监控网络接口带宽的示范脚本。通过介绍,读者将了解如何监视网络接口带宽并以此为依据做出相应的调整。

Unix/Linux 网络接口管理相关命令介绍

获取网络适配器列表信息

在获知网络接口使用状态之前,你可能需要知道你当前的系统使用的网络适配器,在 Linux 和 AIX 中查看网络设备器的属性使用不同的命令,下面的例子给出了在不同系统上如何查看网络设备器的属性。
Linux 系统启动加载网卡驱动会输出识别到的所有网络适配器信息。dmesg 显示系统开机信息。所以可以利用该命令取得系统网络适配器列表。清单 1 命令输出显示共有 2 块网卡,eth0 与 eth1,其中仅 eth1 被启用。

清单 1. 在 RHEL5.3 系统上查看网络适配器

1
2
3
4
5
6
7
8
# dmesg|grep -i eth
 IBM eHEA ethernet device driver (Release EHEA_0092-03)
 ehea: eth0: Jumbo frames are enabled
 ehea: eth0 -> logical port id #1
 ehea: eth1: Jumbo frames are enabled
 ehea: eth1 -> logical port id #2
 ehea: eth1: Physical port up
 eth1: no IPv6 routers present

查看网络接口状态

网络接口状态包括接口是否启用,是否设置 IP 地址、MTU 大小、收发的包数等,查询的命令为 ifconfig, 在不同操作系统其输出格式略有不同。
清单 3 为在 RHEL5.3 上的输出,其显示两个以太网络接口,eth0 未配置 ip 地址,未被启用;eth1 配置了 IP 地址并被启用。
清单 3. 在 RHEL5.3 系统上查看网络接口状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# ifconfig -a
 eth0      Link encap:Ethernet  HWaddr 00:1A:64:44:AC:34
          BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b) 
 
 eth1      Link encap:Ethernet  HWaddr 00:1A:64:44:AC:35
          inet addr:9.114.70.151  Bcast:9.114.70.255  Mask:255.255.255.128
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:12337126 errors:0 dropped:0 overruns:0 frame:0
          TX packets:6250179 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:17295472097 (16.1 GiB)  TX bytes:673204981 (642.0 MiB)
 lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:20168 errors:0 dropped:0 overruns:0 frame:0
          TX packets:20168 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:1989243 (1.8 MiB)  TX bytes:1989243 (1.8 MiB)

查看网络接口连接属性

网络接口连接属性包括连接模式、连接速度、链路状态、协商方式等。
Linux 上用于查询及设置以太网卡参数的一个常用命令是 ethtool,它可以获取网卡的各种详细的诊断信息,包括连接模式(全双工 / 半双工)、连接速度(10M/100M/1000M 等)、是否支持自动协商等、链路状态、驱动版本、总线位置等等。ethtool 的查询以及配置功能需要相应网卡设备驱动的支持,从本质上说,ethtool 的功能是调用驱动提供的 ethtool 接口,来实现用户所要求的操作。基本上,Linux 2.4 以上内核的网卡驱动均支持这个命令。但根据具体驱动的不同,显示的信息可能大同小异。
清单 5. 在 RHEL5.3 系统上查看网络适配器连接属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# ethtool eth1
 Settings for eth1:
        Supported ports: [ FIBRE ]
        Supported link modes:   10baseT/Half 10baseT/Full
                                100baseT/Half 100baseT/Full
                                1000baseT/Full
        Supports auto-negotiation: Yes
        Advertised link modes:  10000baseT/Full
        Advertised auto-negotiation: Yes
        Speed: 1000Mb/s
        Duplex: Full
        Port: FIBRE
        PHYAD: 0
        Transceiver: internal
        Auto-negotiation: on
        Current message level: 0x000000cc (204)
        Link detected: yes 
 
主要字段含义:
 Supported ports 		支持的端口类型
 Supported link modes 	        支持的连接模式
 Supports auto-negotiation 	是否支持自动协商
 Speed 				当前的连接速度
 Duplex 			当前的双工状态
 Port 				端口类型
 Auto-negotiation 		自动协商状态
 Link detected 			链路状态

显示网络接口流量

Linux 上,/proc 文件系统提供了大量的信息反映系统的各种运行状态,包括许多网络相关的统计信息。其中文件 /proc/net/dev 实时反映了网络接口的流量信息。清单7显示了 eth1 当前共接收了 17295646453 字节,发送了 673360865 字节。
清单 7. 在 RHEL5.3 系统上查看网络流量

1
2
3
4
5
6
7
8
9
10
 # cat /proc/net/dev
 Inter-|   Receive                                                |  Transmit
 face |bytes    packets errs drop fifo frame compressed
 multicast|bytes    packets errs drop fifo colls carrier compressed
    lo: 1989443   20172    0    0    0     0          0         0
        1989443   20172    0    0    0     0          0         0
   eth0:      0       0    0    0    0     0          0         0
              0       0    0    0    0     0          0         0
   eth1:17295646453 12338767    0    0     0          0         0      1406
        673360865    6251399    0    0     0          0         0          0

主要字段含义:
bytes 发送或接受的总字节数
packets 发送或接受的报文总数
errs 被设备驱动监测到发送或接受的错误报文总数
drop 由于系统资源限制,被设备驱动丢弃的报文总数
fifo FIFO 缓存错误数
frame 帧错误数
compressed 发送或接受的压缩报数
multicast 接受到的多播报数
colls 接口检测到的冲突数
carrier 连接介质出现故障次数 , 如 : 网线接触不良


UNIX/Linux 系统网络接口带宽监控自动化脚本示例

前文介绍了 AIX 与 Linux 网络接口带宽监控的手段,本节将结合实例介绍网络接口带宽监控的自动化脚本的设计和实现。

设计思路

1 . 监控指标
监控指标选定为网络接口带宽占用率,即网络接口当前流速占网络接口连接速度的比率,网络接口当前流速可通过一个较短时间间隔内的流量变化除以时间间隔获得。下文将以网络接口带宽利用率为例进行监控脚本的设计。
2 .监控手段
为计算当前流速,脚本需要实时捕获经过网络接口的流量。对于 AIX, 需要调用命令“entstat -d”以获取流量信息;对于 Linux, 需要实时查询文件 /proc/net/dev。调用或查询的时间间隔和总数目可以通过脚本本身的参数指定。
3. 告警机制
一般来说,如果网络接口带宽使用率达到 80% 或 85%, 通常会视为网络接口较忙,脚本将向管理员发送告警邮件。
4 .日志
要保留网络接口流量,告警等原始信息,便于以后进行问题分析、定位。

网络接口带宽分析和告警自动脚本

结合上文设计思路,笔者开发了网络接口带宽分析和告警脚本 bandmonitor.sh, 我们的脚本在 RHEL 5.3、SLES 11、AIX 5.3 和 AIX 6.1 上测试通过。
脚本 bandmonitor.sh 的第一部分先进行了初始化,检验并处理输入参数,对未输入的参数指定默认值。

清单 9. bandmonitor.sh 脚本初始化部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#!/bin/ksh
 # ==============================================================
 # Script Name:  bandmonitor.sh
 # Desciption:   to monitor bandwidth utilization of specified Ethernet
 # interface
 # Date:         JUNE 15, 2009
 # =============================================================
 # -------------------------------------------------------------
 # Function definitions...                           函数定义
 # -------------------------------------------------------------
 function usage {
    echo ""
    echo "usage: bandmonitor.sh -i interface [ -l LogFile ] \
 [ -s durationseconds ] [ -c count] [ -u Utilization ]"
    echo ""
    echo "For example: bandmonitor.sh -i eth1 -l /tmp/logFile \
 -s 30 -c 200000 -u 80 "
    exit 1
 } 
 
 # ---------------------------------------------------------------
 # Process command-line arguments                  处理命令行参数
 # ---------------------------------------------------------------
 while getopts :i:l:s:u:c: opt
 do
        case "$opt" in
        i) INT="$OPTARG";;
        l) LogFile="$OPTARG";;
        s) SEC="$OPTARG";;
        u) Util="$OPTARG";;
        c) COUNT="$OPTARG";;
        \?) usage;;
        esac
 done
 # ---------------------------------------------------------------
 # Input validation                                   输入校验
 # --------------------------------------------------------------- 
 
 if [ -z "$INT" ]
 then
        echo "error: invalid Augument interface in OPTION -i "
        usage
        exit 1
 fi 
 
 # ---------------------------------------------------------------
 # Set values, if unset...                              设置默认值
 # --------------------------------------------------------------- 
 
 # 设置日志文件名
 LogFile=${LogFile:-${INT}.log}
 # 设置查询网络接口流量的时间间隔
 SEC=${SEC:-30}
 # 设置网络接口占用率的门限值
 Util=${Util:-'80'}
 # 设置查询网络接口流量的次数
 COUNT=${COUNT:-172800}

接下来, bandmonitor.sh 脚本查询网络接口连接模式和连接速度,对于 AIX 与 Linux 将调用不同的命令。
bandmonitor.sh 脚本查询网络接口连接模式和连接速度

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
 # ----------------------------------------------------------------
 # Query duplex type and speed              查询连接模式和连接速度
 # ----------------------------------------------------------------
 OS=`uname`
 case "$OS" in
 AIX)
        # 获取网络接口连接速度和连接模式
        Media=`entstat -d ${INT}|grep 'Media Speed Running'`
        DuplexType=`echo $Media|awk '{print $6}'`
        Speed=`echo $Media|awk '{print $4}'` 
 
		 # 获取启动监控时网络接口接收和发送的字节数
        Traffic=`entstat ${INT}|grep Bytes`
        OLD_TRAN=`echo ${Traffic}|awk '{print $2}'`
        OLD_RECV=`echo ${Traffic}|awk '{print $4}`
        ;;
 Linux)
        # 获取网络接口连接速度和连接模式
		 DuplexType=`ethtool ${INT}|grep Duplex|awk '{print $2}`
        Speed=`ethtool ${INT}|grep Speed|awk '{print $2}' \
 |sed 's/Mb\/s//` 
 
		 # 获取启动监控时网络接口已接收和已发送的字节数
        Traffic=`grep ${INT} /proc/net/dev`
        OLD_TRAN=`echo ${Traffic}|awk '{print $1}'|cut -d: -f2`
        OLD_RECV=`echo ${Traffic}|awk '{print $9}`
        ;;
 *)      echo "not support $OS operating system!"
        exit 1;
        ;; 
 
 esac 
 
 # 在日志文件中记录监测信息,包括启动时间,监测网络接口,接口工作状态和告警门限
 echo "Start to monitor interface ${INT} at `date +%Y%m%d%H%M%S`."  \
 >> ${LogFile}
 echo "Interface ${INT} is working on Duplex:${DuplexType} \ Speed:${Speed}." \
       >> ${LogFile}
 echo "Utilization threshold is ${Util} percent." >> ${LogFile}

清单 11 中的脚本按不同操作系统实现了网络流量的监控,并按照网络连接的单工或双工模式计算网络接口带宽占用率,如果占用率超出最初设计的门限值,即发送告警邮件给管理员。
清单 11. bandmonitor.sh 监控网络接口流量部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# ----------------------------------------------------------------
 # Send admin an alert if bandwidth utilization reach defined threshold
 # 如果带宽利用率达到门限值即发出告警邮件
 #---------------------------------------------------------------- 
 
 echo "Network traffic recording....." >> ${LogFile} 
 
 Alarm="NO"
 n=1 
 
 # 计算达到告警门限时所允许通过流量的字节数
 BYTETHRES=`expr ${Speed} \* 1024 \* 1024 \* ${Util} \* ${SEC} / 100`
 while [ n -le $COUNT ]
 do
        case "$OS" in
        AIX)
		        # 获取网络接口已接收和已发送的字节数
                Traffic=`entstat ${INT}|grep Bytes`
                Transmit=`echo ${Traffic}|awk '{print $2}'`
                Receive=`echo ${Traffic}|awk '{print $4}`
                ;;
        Linux)
                # 获取网络接口已接收和已发送的字节数
                Traffic=`grep ${INT} /proc/net/dev`
                Transmit=`echo ${Traffic}|awk '{print $1}'|cut -d: -f2`
                Receive=`echo ${Traffic}|awk '{print $9}`
                ;;
        *)      echo "not support $OS operating system!"
                exit 1;
                ;; 
 
        esac 
 
        case "$DuplexType" in
        Full)
               # 连接模式全双工时,需要分别计算发送和接收流量是否超出门限
               if [ `expr $Transmit - $OLD_TRAN` -ge $BYTETHRES ] || \
                [ `expr $Receive - $OLD_RECV` -ge $BYTETHRES ] ;then
                        Alarm="YES"
                fi 
 
                ;;
        Half)
                # 连接模式半双工时,需要合计计算发送和接收流量是否超出门限
                if [ `expr $Transmit - $OLD_TRAN + $Receive - $OLD_RECV` \
                       -ge $BYTETHRES ] ;then
                        Alarm="YES"
                fi 
 
                ;;
        *)      echo "not support Duplex type!"
                exit 1;
                ;; 
 
        esac 
 
        # 在日志中记录流量信息
        echo "INT:${INT}        TIME:`date +%Y%m%d%H%M%S`        \
        TRANS:${Transmit}       RECV:${Receive} ALARM:${Alarm}" \
        >> ${LogFile} 
 
        # 如果超出告警门限, 给管理员发送告警门限
        if [ $Alarm = "YES" ];then
                echo "INT:${INT}      TIME:`date +%Y%m%d%H%M%S`     \
                TRANS:${Transmit}  RECV:${Receive} ALARM:${Alarm}" \
                >> mail.tmp
                mail -s "Bandwidth Alert"  root@localhost< mail.tmp
        fi 
 
        # 设置下次循环前重值
        OLD_TRAN=$Transmit
        OLD_RECV=$Receive
        Alarm="NO"
        sleep $SEC
        n=`expr $n + 1` 
 
 done 
 
 exit 0

脚本使用示例

以下为 bandmonitor.sh 脚本在 AIX 上使用示例。
1 .编辑 crontab 文件,每天零点运行一次 bandmonitor.sh 脚本。其中,-s 30,  表示脚本每 30 秒查询并计算网络接口带宽利用率,– c 172800,将查询计算 172800 次,这两个参数保证脚本能运行一天时间, -u 85,表示该接口带宽利用率门限值设为 85%,监控日志可通过– l 参数指定,本例采用默认值,即为 /root/en0.log 文件。

清单 12. 编辑 crontab

1
2
3
4
 [AIXn01]> crontab – e
 # start to monitor bandwidth of interface en0 every 0 o ’ clock
 0 0 * * * /root/bandmonitor.sh -i en0 – s 30 – c 172800 – u 85 \
 >/tmp/bandmonitor.out 2>&1

2 .用户收到告警邮件,需要进一步查询历史记录时,可查看日志文件。

清单 13. 查看日志文件

1
2
3
4
5
6
7
8
 c209f7n16:/root # cat eth0.log|more
 Start to monitor interface eth0 at 20090721074128.
 Interface eth0 is working on Duplex:Half Speed:100.
 Utilization threshold is 80 percent.
 Network traffic recording.....
 INT:eth0   TIME:20090721074128   TRANS:570460766 RECV:28919401   ALARM:NO
 INT:eth0    TIME:20090721074158   TRANS:570462132 RECV:28923747   ALARM:NO
 INT:eth0    TIME:20090721074228   TRANS:570463752 RECV:28925435   ALARM:NO