阿里云轻量服务器出网流量监控脚本
最近阿里云的客服打过几次电话给我,都是些普通的推广与询问使用情况这样子。一般这种情况我都是敷衍一下了事,直到昨天听到一客服说到让我关心一下我的轻量服务器的账单情况,我才想起轻量服务器是有流量限额的,超了就会产生额外费用。
为了做好防护,我在阿里云的控制台上找相关的监控报警设置,费用成本监控等等入口,真的搞到我头昏眼花。
设置完感觉还不保险,想到之前在 Cloudcone 的机子上装过一个流量监控工具 vnstat,心想这样子的话能不能利用这个工具来弄一个监控流量的脚本,如果流量到达某个值就会自动关机,避免高额流量费用的产生。
将我的需求传递给 DeepSeek,得到以下脚本:
监控每 5 分钟产生的出网流量
/usr/local/bin/auto_shutdown_if_5min_traffic_high.sh
——「脚本已经通过 iperf3 测试成功让服务器关机」
#!/bin/bash
INTERFACE="eth0"
THRESHOLD_MIB=1000 # 1 GiB (实际 1024 MiB,可按需修改)
LOG_FILE="/var/log/traffic_check.log"
CACHE_FILE="/var/log/last_tx_value"
# 获取当前出网流量字段(vnstat 第5字段)
RAW_TX_FIELD=$(vnstat --oneline -i "$INTERFACE" | awk -F ';' '{print $5}')
# 提取数值和单位
if [[ $RAW_TX_FIELD =~ ([0-9.]+)\ (GiB|MiB) ]]; then
TX_VALUE=${BASH_REMATCH[1]}
UNIT=${BASH_REMATCH[2]}
else
echo "$(date) - 无法解析流量值: $RAW_TX_FIELD" >> "$LOG_FILE"
exit 1
fi
# 单位转换为 MiB
case $UNIT in
"GiB") TX_VALUE_MIB=$(echo "scale=2; $TX_VALUE * 1024" | bc) ;;
"MiB") TX_VALUE_MIB=$TX_VALUE ;;
*)
echo "$(date) - 未知单位: $UNIT" >> "$LOG_FILE"
exit 1
;;
esac
# 校验数据有效性
if [[ ! "$TX_VALUE_MIB" =~ ^[0-9.]+$ ]]; then
echo "$(date) - 无效的流量值: $TX_VALUE_MIB" >> "$LOG_FILE"
exit 1
fi
# 初始化或读取缓存
if [ ! -f "$CACHE_FILE" ]; then
echo "$TX_VALUE_MIB" > "$CACHE_FILE"
echo "$(date) - 初始化 TX 流量值: ${TX_VALUE_MIB} MiB" >> "$LOG_FILE"
exit 0
fi
LAST_TX=$(cat "$CACHE_FILE")
if [[ ! "$LAST_TX" =~ ^[0-9.]+$ ]]; then
echo "$(date) - 缓存值无效,重新初始化为当前值: ${TX_VALUE_MIB} MiB" >> "$LOG_FILE"
echo "$TX_VALUE_MIB" > "$CACHE_FILE"
exit 0
fi
# 计算增量(浮点数计算)
DELTA_MIB=$(echo "scale=2; $TX_VALUE_MIB - $LAST_TX" | bc)
DELTA_INT=$(echo "$DELTA_MIB" | awk -F '.' '{print $1}') # 取整数部分
# 更新缓存并记录日志
echo "$TX_VALUE_MIB" > "$CACHE_FILE"
echo "$(date) - 上次 TX: ${LAST_TX} MiB, 当前 TX: ${TX_VALUE_MIB} MiB, 增量: ${DELTA_MIB} MiB" >> "$LOG_FILE"
# 判断阈值
if [ "$DELTA_INT" -ge "$THRESHOLD_MIB" ]; then
echo "$(date) - ⚠️ 5分钟出网流量超过阈值 (${THRESHOLD_MIB} MiB),正在关机..." >> "$LOG_FILE"
shutdown -h now
fi
监控当月累计出网流量
cat /usr/local/bin/auto_shutdown_if_traffic_high.sh
#!/bin/bash
INTERFACE="eth0"
THRESHOLD_MIB=819200 # 800 GiB(800*1024=819200 MiB)
LOG_FILE="/var/log/traffic_check.log"
# 获取当月出网流量字段(vnstat 第10字段)
RAW_TX_FIELD=$(vnstat --oneline -i "$INTERFACE" | awk -F ';' '{print $10}')
# 提取数值和单位
if [[ $RAW_TX_FIELD =~ ([0-9.]+)\ (GiB|MiB) ]]; then
TX_VALUE=${BASH_REMATCH[1]}
UNIT=${BASH_REMATCH[2]}
else
echo "$(date) - 无法解析流量值: $RAW_TX_FIELD" >> "$LOG_FILE"
exit 1
fi
# 单位转换为 MiB
case $UNIT in
"GiB") TX_VALUE_MIB=$(echo "scale=2; $TX_VALUE * 1024" | bc) ;;
"MiB") TX_VALUE_MIB=$TX_VALUE ;;
*)
echo "$(date) - 未知单位: $UNIT" >> "$LOG_FILE"
exit 1
;;
esac
# 校验数据有效性
if [[ ! "$TX_VALUE_MIB" =~ ^[0-9.]+$ ]]; then
echo "$(date) - 无效的流量值: $TX_VALUE_MIB" >> "$LOG_FILE"
exit 1
fi
# 记录日志并判断阈值(浮点数比较)
echo "$(date) - 当月累计出网流量TX: ${TX_VALUE_MIB} MiB" >> "$LOG_FILE"
if [ $(echo "$TX_VALUE_MIB >= $THRESHOLD_MIB" | bc) -eq 1 ]; then
echo "$(date) - ⚠️ 累计出网流量已超过 ${THRESHOLD_MIB} MiB,正在关机..." >> "$LOG_FILE"
shutdown -h now
fi
赋予执行权限
chmod +x /usr/local/bin/auto_shutdown_if_5min_traffic_high.sh
chmod +x /usr/local/bin/auto_shutdown_if_traffic_high.sh
cron 任务
crontab -e
添加上述两个脚本
*/2 * * * * /usr/local/bin/auto_shutdown_if_traffic_high.sh
*/5 * * * * /usr/local/bin/auto_shutdown_if_5min_traffic_high.sh
以下为使用 iperf3 来测试 5 分钟后自动关机的日志
Wed May 14 10:10:02 AM CST 2025 - 上次 TX: 1228.80 MiB, 当前 TX: 1228.80 MiB, 增量: 0 MiB
Wed May 14 10:12:01 AM CST 2025 - 当月累计出网流量TX: 1239.04 MiB
Wed May 14 10:14:01 AM CST 2025 - 当月累计出网流量TX: 1239.04 MiB
Wed May 14 10:15:01 AM CST 2025 - 上次 TX: 1228.80 MiB, 当前 TX: 2304.00 MiB, 增量: 1075.20 MiB
Wed May 14 10:15:01 AM CST 2025 - ⚠️ 5分钟出网流量超过阈值 (1000 MiB),正在关机...