脚本
sudo tee /data/net_monitor.sh > /dev/null <<'EOF'
#!/usr/bin/env bash
# =========================
# VPS 出网流量监控脚本
# =========================
# 功能:
# 1. 监控 VPS 出网流量
# 2. 出网流量 >= 5MB/s 时运行命令
# 3. 出网流量为 0 时停止命令
# 4. 日志写入 /var/log/net_monitor.log
# 5. 日志文件超过 10MB 自动轮换
# =========================
# 日志文件
LOG_FILE="/var/log/net_monitor.log"
# 日志最大大小:10MB
MAX_LOG_SIZE=$((10 * 1024 * 1024))
# 网卡名称
# 留空表示自动识别默认公网出口网卡
# 你的 VPS 当前一般是 eth0
IFACE=""
# 出网流量阈值:5MB/s
THRESHOLD=$((5 * 1024 * 1024))
# 检测间隔:1秒
INTERVAL=1
# =========================
# 需要运行和停止的命令
# =========================
# 还没想好命令就保持为空
# 示例:
# START_COMMAND="/data/start.sh"
# STOP_COMMAND="/data/stop.sh"
START_COMMAND=""
STOP_COMMAND=""
# 状态变量
running=0
child_pid=""
detect_iface() {
ip route get 223.6.6.6>/dev/null | awk '{
for (i=1; i<=NF; i++) {
if ($i == "dev") {
print $(i+1)
exit
}
}
}'
}
rotate_log() {
if [ -f "$LOG_FILE" ]; then
size=$(stat -c%s "$LOG_FILE" 2>/dev/null || echo 0)
if [ "$size" -ge "$MAX_LOG_SIZE" ]; then
mv "$LOG_FILE" "${LOG_FILE}.1" 2>/dev/null
touch "$LOG_FILE"
chmod 644 "$LOG_FILE"
fi
else
touch "$LOG_FILE"
chmod 644 "$LOG_FILE"
fi
}
log_msg() {
rotate_log
echo "$(date '+%F %T') $*" >> "$LOG_FILE"
}
get_tx_bytes() {
awk -v iface="$IFACE" '
$1 == iface ":" {
print $10
}
' /proc/net/dev
}
start_command() {
log_msg "出网流量 ${speed_mb}MB/s,达到阈值 5MB/s"
log_msg "当前速度:${speed} bytes/s"
if [ -n "$START_COMMAND" ]; then
log_msg "准备运行命令:$START_COMMAND"
bash -c "$START_COMMAND" &
child_pid=$!
log_msg "命令已启动,PID=$child_pid"
else
log_msg "START_COMMAND 未设置,只记录日志,不执行实际命令"
fi
running=1
}
stop_command() {
log_msg "出网流量为 0,准备停止命令"
if [ -n "$STOP_COMMAND" ]; then
log_msg "准备执行停止命令:$STOP_COMMAND"
bash -c "$STOP_COMMAND"
stop_code=$?
log_msg "STOP_COMMAND 执行完成,退出码=$stop_code"
else
log_msg "STOP_COMMAND 未设置"
fi
if [ -n "$child_pid" ] && kill -0 "$child_pid" 2>/dev/null; then
log_msg "准备停止后台进程,PID=$child_pid"
kill "$child_pid" 2>/dev/null
wait "$child_pid" 2>/dev/null
log_msg "后台进程已停止,PID=$child_pid"
else
log_msg "没有需要 kill 的后台进程"
fi
child_pid=""
running=0
}
cleanup() {
log_msg "收到退出信号,脚本准备退出"
if [ "$running" -eq 1 ]; then
stop_command
fi
log_msg "网络监控脚本已退出"
exit 0
}
trap cleanup INT TERM
# 自动识别网卡
if [ -z "$IFACE" ]; then
IFACE=$(detect_iface)
fi
# 如果自动识别失败,默认使用 eth0
if [ -z "$IFACE" ]; then
IFACE="eth0"
fi
prev_tx=$(get_tx_bytes)
if [ -z "$prev_tx" ]; then
log_msg "错误:无法读取网卡 $IFACE,请检查网卡名称"
exit 1
fi
log_msg "网络监控启动,网卡=$IFACE,阈值=5MB/s,日志限制=10MB"
while true; do
sleep "$INTERVAL"
curr_tx=$(get_tx_bytes)
if [ -z "$curr_tx" ]; then
log_msg "错误:无法读取网卡 $IFACE"
exit 1
fi
diff=$((curr_tx - prev_tx))
# 防止网卡重置后出现负数
if [ "$diff" -lt 0 ]; then
log_msg "检测到网卡计数器重置,重新记录基准值"
prev_tx=$curr_tx
continue
fi
speed=$((diff / INTERVAL))
speed_mb=$((speed / 1024 / 1024))
# 出网流量为 0,停止命令
if [ "$speed" -eq 0 ]; then
if [ "$running" -eq 1 ]; then
stop_command
fi
# 出网流量达到 5MB/s,运行命令
elif [ "$speed" -ge "$THRESHOLD" ]; then
if [ "$running" -eq 0 ]; then
start_command
fi
fi
prev_tx=$curr_tx
done
EOF
sudo chmod +x /data/net_monitor.sh
测试脚本:
sudo /data/net_monitor.sh
没报错就按 Ctrl+C 停止测试,然后重启后台服务:
sudo systemctl daemon-reload
sudo systemctl restart net_monitor.service
sudo systemctl enable net_monitor.service
sudo systemctl status net_monitor.service
查看日志:
sudo tail -f /var/log/net_monitor.log
以后要设置真正运行和停止的命令,只改这两行:
START_COMMAND=""STOP_COMMAND=""
例如:
START_COMMAND="/data/start.sh"STOP_COMMAND="/data/stop.sh"
改完后执行:
sudo systemctl restart net_monitor.service
日志效果类似:
2026-05-06 23:50:01 网络监控启动,网卡=eth0,阈值=5MB/s,日志限制=10MB
2026-05-06 23:51:08 出网流量 7MB/s,达到阈值 5242880 bytes/s
2026-05-06 23:51:08 准备运行命令:/data/start.sh
2026-05-06 23:51:08 命令已启动,PID=12345
2026-05-06 23:55:31 出网流量为 0,准备停止命令
2026-05-06 23:55:31 准备执行停止命令:/data/stop.sh
2026-05-06 23:55:31 STOP_COMMAND 执行完成,退出码=0
2026-05-06 23:55:31 后台进程已停止,PID=12345