公众号旧文

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
   |
   ↓
停止继续消耗流量