前言
一、脚本功能
二、实现原理
三、Shell 脚本实现
四、关键知识点解析
1. Bash 关联数组
2. 命令组 { } 与子 Shell ( )
3. 字符串拼接换行
4. 流量计算逻辑
五、测试方法
六、优化建议
七、总结
前言
在生产环境中,监控服务器的 网络流量 非常重要,尤其是下载/上传流量突然激增时,需要及时告警。本文将介绍如何使用 Shell 脚本 + msmtp 实现网络流量监控和邮件告警,并解析其中的关键知识点。
一、脚本功能
-
监控指定网卡的下载(RX)和上传(TX)流量
-
当流量超过阈值(MB)时触发邮件告警
-
支持多网卡监控
-
可生成日志,记录每次流量情况
二、实现原理
-
采集网卡流量
Linux 系统中,每个网卡的流量信息在:
/sys/class/net/<网卡名称>/statistics/rx_bytes # 下载字节数
/sys/class/net/<网卡名称>/statistics/tx_bytes # 上传字节数
这些值是 累计字节数。
-
计算流量
公式:
实际流量 = 第二次采样值 - 第一次采样值
-
RX = 下载流量(字节)
-
TX = 上传流量(字节)
-
转换为 MB:
RX_MB = RX / 1024 / 1024
-
告警触发
-
当 RX_MB 或 TX_MB ≥ 阈值时,拼接告警信息
-
通过
msmtp
发送邮件
-
日志记录
-
每次采样后的流量记录到日志文件
-
告警信息也记录到日志
三、Shell 脚本实现
#!/bin/bash#要监控的网卡列表 NET_LIST=("eth0") #设置阈值(MB) NET_WARNING=0 #采集时间 TIME=5 #设置日志文件位置 LOG_FILE="/var/log/net_warning.log" #设置收件人 MAIL_TO="3426848201@qq.com,2270993679@qq.com" #设置标题 TITLE="网络流量告警" #设置发送邮件函数 send_file(){local msg="$1"{echo "Subject: $TITLE"echo "To: $MAIL_TO"echoecho -e "$msg"} | msmtp -t } #设置日志函数 log(){local msg="$1"echo -e "$(date +"%F %T") $msg" >> "$LOG_FILE" } #设置关联数组用于保存采集数据 #关联数组可以使用字符串作为索引 declare -A RX_BYTES_1 declare -A TX_BYTES_1 declare -A RX_BYTES_2 declare -A TX_BYTES_2 #进行第一次采集 for IF in "${NET_LIST[@]}"; doRX_BYTES_1[$IF]=$(cat /sys/class/net/$IF/statistics/rx_bytes)TX_BYTES_1[$IF]=$(cat /sys/class/net/$IF/statistics/tx_bytes) done #等待60秒再进行采集,确保数据合理稳定 sleep $TIME #进行第二次采集 for IF in "${NET_LIST[@]}"; doRX_BYTES_2[$IF]=$(cat /sys/class/net/$IF/statistics/rx_bytes)TX_BYTES_2[$IF]=$(cat /sys/class/net/$IF/statistics/tx_bytes) done #设置空变量用于保存告警信息 ALERT_MSG="" #进行流量计算,判断阈值 #计算公式为 #实际下载流量 = 第二次采样下载字节数 - 第一次采样下载字节数 #实际上传流量 = 第二次采样上传字节数 - 第一次采样上传字节数 #1MB = 1024x1024字节,RX/TX计算的默认为字节数,所以需要/1024/1024换算成MB for IF in "${NET_LIST[@]}"; doRX=$((RX_BYTES_2[$IF] - RX_BYTES_1[$IF]))TX=$((TX_BYTES_2[$IF] - TX_BYTES_1[$IF]))RX_MB=$((RX / 1024 / 1024))TX_MB=$((TX / 1024 / 1024))log "接口 $IF: 下载${RX_MB}MB, 上传${TX_MB}MB"if [ $RX_MB -ge $NET_WARNING ]; thenALERT_MSG+="接口 $IF 下载流量超限: ${RX_MB}MB"$'\n'fi if [ $TX_MB -ge $NET_WARNING ]; thenALERT_MSG+="接口 $IF 上传流量超限: ${TX_MB}MB"$'\n'fi done #发送邮件进行告警 if [ -n "$ALERT_MSG" ]; then#调用log和send_file函数将告警信息传递给$1,通过send_file函数发送邮件log "触发告警:\n$ALERT_MSG"send_file "$ALERT_MSG" fi
四、关键知识点解析
1. Bash 关联数组
declare -A RX_BYTES_1
-
可以用 字符串索引(网卡名)保存数据
-
示例:
RX_BYTES_1["eth0"]=123456
2. 命令组 { }
与子 Shell ( )
{ echo "Subject: $TITLE"
echo "To: $MAIL_TO"
echo
echo -e "$msg" } | msmtp -t
-
{ ... }
在 当前 shell 执行,不创建子 shell -
(...)
会在 子 shell 执行,变量修改不会影响外部
3. 字符串拼接换行
ALERT_MSG+="接口 $IF 下载流量超限: ${RX_MB}MB"$'\n'
-
$'\n'
生成实际换行字符 -
echo -e "$ALERT_MSG"
可正确显示换行
4. 流量计算逻辑
RX=$((RX_BYTES_2[$IF] - RX_BYTES_1[$IF]))
TX=$((TX_BYTES_2[$IF] - TX_BYTES_1[$IF]))
-
计算两次采样的差值
-
单位是字节(Bytes),转换 MB 后用于判断阈值
五、测试方法
为了测试脚本功能,可以 临时降低阈值和缩短采样间隔:
NET_WARNING=1 # 阈值 1MB,方便触发
TIME=5 # 采样间隔 5 秒
-
执行脚本:
sh NetWork上传下载监控.sh
-
生成日志:
cat /var/log/net_warning.log
-
检查邮件是否收到
-
可以用下载或上传测试流量:
wget http://speedtest.tele2.net/10MB.zip -O /dev/null
curl -T localfile
ftp://ftpserver/ --user user:pass
-
测试完成后,恢复正式阈值和采样间隔
六、优化建议
-
日志按天生成,避免过大
-
支持多个收件人
-
可通过命令行参数调整网卡列表和阈值
-
可通过 cron 定时执行,实现 持续监控
七、总结
-
利用
/sys/class/net/.../statistics/
获取网卡累计流量 -
关联数组保存采样数据,计算两次差值得到实际流量
-
用
$'\n'
拼接告警信息,并通过msmtp
发送邮件 -
日志记录每次采样及告警信息
-
可以通过调整阈值和采样间隔快速测试脚本