vnStat 是一款开源的网络流量统计工具,可以方便的查看当天,当月流量统计。官网地址:
https://humdi.net/vnstat/
安装
在 Debian/Ubuntu 下非常简单
sudo apt install vnstat vnstati
假设网卡名为 eth0
,该配置在 /etc/vnstat.conf
中,安装结束后初始化数据库
sudo vnstat -u -i eth0
添加为开机启动
sudo update-rc.d vnstat enable
使用
直接输入 vnstat
vnstat -l # 或者 `--live` 实时流量
vnstat -h # 按小时查询流量
vnstat -d # 按日显示流量信息
vnstat -w # 按周显示流量信息
vnstat -m # 按月显示流量信息
vnstat -t # 显示流量最高top10天
图形化输出可以使用 vnstati
,将月流量统计图输出到图片
vnstati -i eth0 - -months - -output /dir/month.png
获取每月用量
#!/bin/bash
# 绑定网卡,一般默认eth0, 根据实际情况填写
interface="eth0"
# 定义阈值,单位GiB
traffic_limit="14"
# 获取每月用量 $11:进站+出站;$10是:出站;$9是:进站
traffic="$(vnstat --oneline -i "${interface}" | awk -F ';' '{print $11}')"
if [[ "${traffic}" =~ ^.+GiB$ ]] && [[ "${traffic%.*}" -ge ${traffic_limit} ]]; then
echo "当前流量超过限制:${traffic}"
# 执行后续操作
# sudo halt
else
echo "当前流量未超过限制:${traffic}"
fi
脚本
#!/bin/bash
# 定义阈值(以GB为单位) 执行 vnstat --json 命令并将输出保存到变量中
THRESHOLD_GIB=1700
vnstat_output=$(vnstat --json)
# 提取当前年份和月份
current_year=$(echo "$vnstat_output" | jq -r '.interfaces[0].traffic.month[0].date.year')
current_month=$(echo "$vnstat_output" | jq -r '.interfaces[0].traffic.month[0].date.month')
# 在"month"部分找到相应的"rx"和"tx"值
rx_value_bytes=$(echo "$vnstat_output" | jq -r '.interfaces[0].traffic.month[0].rx')
rx_value_gb=$(echo "scale=2; $rx_value_bytes / 1024 / 1024 / 1024" | bc)
tx_value_bytes=$(echo "$vnstat_output" | jq -r '.interfaces[0].traffic.month[0].tx')
tx_value_gb=$(echo "scale=2; $tx_value_bytes / 1024 / 1024 / 1024" | bc)
# 计算总流量
total_traffic=$(echo "$rx_value_gb + $tx_value_gb" | bc)
echo "当前月份接收流量 : $rx_value_gb GB"
echo "当前月份发送流量 : $tx_value_gb GB"
echo "当前月份流量总计 : $total_traffic GB"
# 检查是否大于阈值
if (( $(echo "$total_traffic > $THRESHOLD_GIB" | bc -l) )); then
echo "流量超过阈值,正在执行关机操作..."
# 如果要执行重启就把下面的#去掉
# sudo halt
else
echo "本月流量充足"
fi
发送 Telegram 通知
## 流量超过阈值就发送消息提醒
### config.json
# {
# "telegram_bot_token": "xxxxx:xxxxxxx",
# "chat_id": "xxxx",
# "monthly_limit_gb": 100
# }
import json
import requests
import schedule
import time
import psutil
from datetime import datetime
def load_config():
with open("config.json", "r") as file:
return json.load(file)
def log_initial_traffic_usage():
today = datetime.now()
if today.day == 1: # Check if it is the first day of the month
net_io = psutil.net_io_counters(pernic=True).get('ens5')
if net_io:
total_bytes_initial = net_io.bytes_sent + net_io.bytes_recv
print(f'{total_bytes_initial}')
with open("traffic_usage.txt", "w") as file:
file.write(f"{total_bytes_initial}\n")
def get_current_month_usage():
try:
with open("traffic_usage.txt", "r") as file:
initial_bytes = int(file.readline().strip())
net_io = psutil.net_io_counters(pernic=True).get('ens5')
if net_io:
current_total_bytes = net_io.bytes_sent + net_io.bytes_recv
used_bytes = current_total_bytes - initial_bytes
used_gb = used_bytes / (1024**3) # Convert to GB
return used_gb
except FileNotFoundError:
print("Initial traffic usage file not found. Make sure it's generated at the beginning of the month.")
return None
def send_telegram_message(message, config):
url = f"https://api.telegram.org/bot{config['telegram_bot_token']}/sendMessage"
data = {
"chat_id": config["chat_id"],
"text": message
}
requests.post(url, data=data)
def check_traffic_and_notify(config):
used_gb = get_current_month_usage()
print(f'Already used: {used_gb} GB')
if used_gb is not None and used_gb > config["monthly_limit_gb"]:
send_telegram_message(f"Attention: Monthly traffic limit exceeded. Used: {used_gb:.2f} GB", config)
config = load_config()
schedule.every().day.at("00:01").do(log_initial_traffic_usage)
schedule.every(15).seconds.do(check_traffic_and_notify, config)
while True:
schedule.run_pending()
time.sleep(1)
总结
有了 vnstat 就可以自己写脚本来定时完成流量监控,比如在 AWS 上,如果发现流量超出了阈值,可以写 Telegram Bot 通知,也可以直接禁用相关的端口。