VPS 出网流量监控脚本,出网流量 >= 5MB/s 时运行命令

脚本

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

如下载任务

START_COMMAND="exec wget --limit-rate=500k -O /dev/null 'https://*.*.com/*file'"
STOP_COMMAND=""