公众号旧文
VPS 流量熔断器:达到 45GB 后自动停止
我有一台 VPS 上运行着 Cloudflared Tunnel 服务。
因为这个服务会持续产生网络流量,而 VPS 的流量额度有限,所以我希望实现一个保护机制:
当这台机器从现在开始累计产生 45GB(入站 + 出站)流量后,自动停止 Cloudflared,避免继续消耗额度。
1. 先确认运行方式
首先查看服务状态:
systemctl status cloudflared
结果:
Unit cloudflared.service could not be found.
说明它并不是 systemd 服务。
于是查看进程:
ps aux | grep cloudflared
发现:
root 257 ... ./cloudflared-linux tunnel --url http://localhost:20254 ...
进一步确认:
ps -o pid,ppid,cmd -p 257
得到:
PID PPID
257 1
说明:
- Cloudflared 是直接运行的进程
- 没有 systemd service
- 父进程是 PID 1
- 后续需要通过杀进程方式停止
2. 获取网卡流量统计
首先确认网卡:
ip -br link
结果:
eth0@if17 UP
Linux 已经提供了网卡统计:
/sys/class/net/eth0/statistics/
其中:
rx_bytes
代表接收流量
tx_bytes
代表发送流量
所以总流量 = rx_bytes + tx_bytes
3. 记录开始计算的时间点
因为需求是再跑45GB,而不是统计历史流量。
所以需要保存一个基准值。
创建:
/var/lib/traffic-limit/start.bytes
里面保存:
375825787773
这个数字代表:
开始监控时,网卡累计产生的总字节数。
之后:
当前总流量 - 起始流量 = 本次消耗
4. 编写流量检测脚本
创建:
/usr/local/bin/traffic-limit.sh
核心逻辑:``
#!/bin/bash
IFACE="eth0"
LIMIT=$((45*1024*1024*1024))
RX=$(cat /sys/class/net/$IFACE/statistics/rx_bytes)
TX=$(cat /sys/class/net/$IFACE/statistics/tx_bytes)
TOTAL=$((RX+TX))
读取当前总流量。
第一次运行时保存基准:
if [ ! -f "$START_FILE" ]; then
echo $TOTAL > $START_FILE
fi
然后计算:
USED=$((TOTAL-START))
转换成人类可读:
USED_GB=$(awk "BEGIN {printf \"%.2f\", $USED/1024/1024/1024}")
输出:
Used 0.04 GB
5. 达到45GB后停止 Cloudflared
关键判断:
if [ "$USED" -ge "$LIMIT" ]; then
达到限制后:
pkill -f "./cloudflared-linux tunnel"
直接结束 Cloudflared 进程。
同时:
touch /var/lib/traffic-limit/blocked
记录已经触发。
6. 使用 systemd timer 每分钟检查
脚本本身不会自动运行,所以创建:
/etc/systemd/system/traffic-limit.service
内容:
[Unit]
Description=Traffic limit monitor
[Service]
Type=oneshot
ExecStart=/usr/local/bin/traffic-limit.sh
然后创建定时器:
/etc/systemd/system/traffic-limit.timer
内容:
[Timer]
OnBootSec=1min
OnUnitActiveSec=1min
表示:
- 开机1分钟后执行
- 每隔1分钟执行一次
启动:
systemctl daemon-reload
systemctl enable --now traffic-limit.timer
7. 验证运行状态
查看 timer:
systemctl list-timers | grep traffic
看到:
traffic-limit.timer traffic-limit.service
说明正常。
查看日志:
journalctl -u traffic-limit.service -f
输出:
traffic-limit.sh: Used 0.00 GB
traffic-limit.sh: Used 0.03 GB
traffic-limit.sh: Used 0.04 GB
说明:
- 定时执行正常
- 流量读取正常
- 累计计算正常
最终效果
现在这台 VPS 的逻辑:
eth0流量
|
↓
读取 rx_bytes + tx_bytes
|
↓
减去启动监控时的流量
|
↓
累计达到45GB
|
↓
pkill Cloudflared
|
↓
停止继续消耗流量