前言:
通过这个脚本,可以自动识别带宽是否低于设定值(如 300 Mbps),如果是,则自动阻断新的下载任务。
使用 iptables 阻止新连接
脚本使用
iptables
来阻止对qBittorrent Web UI
端口(默认是 8080)的访问。这样做的效果是:
新的任务无法添加(因为 Web UI 无法访问)
已有的任务仍然继续下载(不会中断)
自动恢复机制
当带宽恢复正常后,脚本会自动解除 iptables 规则,允许重新配置 qBittorrent。
可选地(通过变量控制)会在恢复后自动重启服务器(用于清理资源或重置状态)。
通知机制
使用 Telegram Bot 和 Email 发送通知,让你及时了解当前带宽状态和系统操作记录。
支持多种消息格式美化,便于阅读。
脚本的“智能判断”逻辑
技术亮点总结
安装方法:
1)新建目录bw-monitor,然后再在这个目录下新建bw-monitor.sh
2)粘贴脚本文件进去保存
#!/bin/bash
set -euo pipefail
# === 用户配置区 ===
TELEGRAM_BOT_TOKEN="#"
TELEGRAM_CHAT_ID="#"
EMAIL="#"
QBITTORRENT_PORT=8080 # qBittorrent Web UI 端口
NOTIFY_INTERVAL_MINUTES=10
MIN_BANDWIDTH_Mbps=300 # 触发限速的带宽阈值
STATE_FILE="/tmp/bw_monitor_state"
LOG_FILE="/var/log/bw-monitor.log"
# 是否在离开低速模式后重启服务器
REBOOT_AFTER_LEAVE_LOW_SPEED=true
# === 通知开关 ===
TELEGRAM_NOTIFY=true # 是否启用 Telegram 通知
EMAIL_NOTIFY=true # 默认关闭邮件通知(可改为 true 启用)
# === 工具路径检查 ===
SPEEDTEST=$(command -v speedtest-cli || command -v speedtest)
MAIL=$(command -v mail || true)
# 获取公网IPv4地址
get_public_ip() {
local ip
ip=$(curl -s --ipv4 http://ifconfig.me)
echo "$ip"
}
# 日志函数
log() {
echo "$(date '+%Y-%m-%d %T') $1" | tee -a "$LOG_FILE"
}
# === 安装 mutt(如果未安装)===
setup_mutt() {
if ! command -v mutt &> /dev/null; then
log "[INSTALL] 安装 mutt..."
apt update && apt install -y mutt
fi
}
# === 通知函数 ===
send_telegram() {
if [[ "$TELEGRAM_NOTIFY" == "true" ]]; then
local msg="$1"
# 替换 \n 字符串为真实换行符
msg=$(echo "$msg" | sed 's/\\n/\n/g')
# 在每行末尾加两个空格以确保 Telegram Markdown 正确换行
msg=$(echo "$msg" | sed 's/$/ /')
curl -s -X POST "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/sendMessage" \
-d chat_id="$TELEGRAM_CHAT_ID" \
-d parse_mode="Markdown" \
-d text="$msg"
fi
}
send_email() {
if [[ "$EMAIL_NOTIFY" == "true" && -n "$EMAIL" ]]; then
local subject="$1"
local body="$2"
# 替换 \n 字符串为真实换行符
body=$(echo "$body" | sed 's/\\n/\n/g')
setup_mutt
# 使用 mutt 发送邮件,确保 UTF-8 编码
echo -e "$body" | mutt -e "set content_type=text/plain; charset=UTF-8" -s "$subject" -- "$EMAIL"
fi
}
notify_user() {
local event="$1"
local bandwidth="$2"
local server_ip="$3"
local container="$4"
local status="$5"
local mode="$6"
local time=$(date "+%Y-%m-%d %H:%M:%S")
local msg_template="🛠️ 事件: $event\n📊 带宽: $bandwidth Mbps\n🖥️ 服务器IP: $server_ip\n🐳 组件: $container\n🕒 时间: $time\n🔗 状态: $status"
send_telegram "$msg_template"
send_email "【带宽通知】$mode 流量模式触发" "$msg_template"
}
# === 网络控制函数 ===
block_qb_connection() {
if ! iptables -C INPUT -p tcp --dport "$QBITTORRENT_PORT" -j DROP 2>/dev/null; then
iptables -I INPUT 1 -p tcp --dport "$QBITTORRENT_PORT" -j DROP
log "[ACTION] 已阻止主机上的 qbittorrent 访问(端口: $QBITTORRENT_PORT)"
fi
}
unblock_qb_connection() {
if iptables -C INPUT -p tcp --dport "$QBITTORRENT_PORT" -j DROP 2>/dev/null; then
iptables -D INPUT -p tcp --dport "$QBITTORRENT_PORT" -j DROP
log "[ACTION] 已解除对主机 qbittorrent 的访问限制(端口: $QBITTORRENT_PORT)"
else
log "[INFO] 当前没有针对 qbittorrent 的限制规则"
fi
}
get_bandwidth_speed() {
local result
result=$($SPEEDTEST --simple)
if [[ $? -eq 0 ]]; then
local down
down=$(echo "$result" | grep 'Download' | awk '{print $2}')
echo "$down"
else
log "[ERROR] Speedtest 失败"
exit 1
fi
}
# === 主逻辑 ===
main() {
log "[INFO] 开始带宽检测..."
# 第一次测速
bandwidth1=$(get_bandwidth_speed)
log "[INFO] 第一次下载速度: ${bandwidth1} Mbps"
# 等待5秒进行第二次测速
sleep 5
bandwidth2=$(get_bandwidth_speed)
log "[INFO] 第二次下载速度: ${bandwidth2} Mbps"
# 判断是否都低于阈值
is_low1=$(echo "$bandwidth1 < $MIN_BANDWIDTH_Mbps" | bc -l)
is_low2=$(echo "$bandwidth2 < $MIN_BANDWIDTH_Mbps" | bc -l)
if [[ "$is_low1" -eq 1 && "$is_low2" -eq 1 ]]; then
is_low_bandwidth=true
elif [[ "$is_low1" -eq 0 && "$is_low2" -eq 0 ]]; then
is_low_bandwidth=false
else
log "[INFO] 两次测速结果不一致,暂不改变状态"
exit 0
fi
last_state=$(cat "$STATE_FILE" 2>/dev/null || echo "")
notify_message=""
SERVER_IP=$(get_public_ip)
if [[ "$is_low_bandwidth" == "true" ]]; then
if [[ "$last_state" != "low" ]]; then
log "[ACTION] 连续两次检测到低速带宽,正在阻止 qbittorrent 访问..."
block_qb_connection
notify_message="⚠️ 进入低速模式"
echo "low" > "$STATE_FILE"
notify_user "$notify_message" "$bandwidth2" "$SERVER_IP" "qbittorrent" "新任务已禁止" "低速"
else
log "[INFO] 当前仍处于低速模式,不重复推送。"
fi
else
if [[ "$last_state" == "low" ]]; then
log "[ACTION] 连续两次检测到高速带宽恢复,解除限制..."
unblock_qb_connection
notify_message="✅ 离开低速模式"
echo "high" > "$STATE_FILE"
notify_user "$notify_message" "$bandwidth2" "$SERVER_IP" "qbittorrent" "新任务已恢复" "高速"
# 判断是否需要重启服务器
if [[ "$REBOOT_AFTER_LEAVE_LOW_SPEED" == "true" ]]; then
log "[ACTION] 正在重启服务器..."
reboot
fi
else
log "[INFO] 当前仍处于高速模式,不推送。"
fi
fi
}
# === 测试通知 ===
test_notification() {
log "[INFO] 发送测试通知..."
local test_ip=$(get_public_ip)
notify_user "🧪 测试通知" "1000" "$test_ip" "qbittorrent" "通知系统正常" "测试"
}
# === 安装依赖 ===
setup_dependencies() {
if ! command -v speedtest-cli &> /dev/null && ! command -v speedtest &> /dev/null; then
log "[INSTALL] 安装 speedtest-cli..."
apt update && apt install -y python3-pip
pip3 install speedtest-cli || apt install -y speedtest-cli
fi
if ! command -v jq &> /dev/null; then
log "[INSTALL] 安装 jq..."
apt update && apt install -y jq
fi
if ! command -v mutt &> /dev/null; then
log "[INSTALL] 安装 mutt..."
apt update && apt install -y mutt
fi
if ! command -v bc &> /dev/null; then
log "[INSTALL] 安装 bc..."
apt update && apt install -y bc
fi
if ! command -v curl &> /dev/null; then
log "[INSTALL] 安装 curl..."
apt install -y curl
fi
}
# === 安装cron任务 ===
setup_cron() {
(crontab -l 2>/dev/null | grep -v "bw-monitor"; echo "*/$NOTIFY_INTERVAL_MINUTES * * * * /opt/bw-monitor/bw-monitor.sh") | crontab -
log "[CRON] 已添加每${NOTIFY_INTERVAL_MINUTES}分钟的检测任务"
}
# === 初始化安装 ===
if [[ "$*" == *"--install"* ]]; then
log "[SETUP] 正在安装 bw-monitor..."
setup_dependencies
mkdir -p /opt/bw-monitor/
cp "$0" /opt/bw-monitor/bw-monitor.sh
chmod +x /opt/bw-monitor/bw-monitor.sh
ln -sf /opt/bw-monitor/bw-monitor.sh /usr/local/bin/bw-monitor
setup_cron
test_notification
log "[SETUP] 安装完成!"
exit 0
fi
# === 执行主程序 ===
main
3)赋予执行权限 sudo chmod +x /opt/bw-monitor/bw-monitor.sh
4)首次运行安装 sudo /opt/bw-monitor/bw-monitor.sh --install
5)手动运行监控 sudo /opt/bw-monitor/bw-monitor.sh
6)查看定时任务 crontab -l
7)如果定时任务没有安装好,可以手动安装下
sudo crontab -e
*/10 * * * * /opt/bw-monitor/bw-monitor.sh
依次ctrl+O,回车,ctrl+X
8)查看日志:tail -f /var/log/bw-monitor.log
或者手动打开日志文件
目录:STATE_FILE="/tmp/bw_monitor_state",LOG_FILE="/var/log/bw-monitor.log"
STATE_FILE
用来保存带宽监控的状态(高速或低速),通过读取和写入这个文件来判断当前是否处于限速模式。LOG_FILE
则是记录脚本执行过程中的日志信息。
下方命令调试使用,可忽略
#模拟低速模式(<300 Mbps)
sudo sed -i '/function get_bandwidth_speed/,+5d' /opt/bw-monitor/bw-monitor.sh
sudo sed -i '/main() {/i get_bandwidth_speed() {\n echo "150"\n}' /opt/bw-monitor/bw-monitor.sh
sudo /opt/bw-monitor/bw-monitor.sh
#模拟高速模式(≥300 Mbps)
sudo sed -i '/function get_bandwidth_speed/,+5d' /opt/bw-monitor/bw-monitor.sh
sudo sed -i '/main() {/i get_bandwidth_speed() {\n echo "500"\n}' /opt/bw-monitor/bw-monitor.sh
sudo /opt/bw-monitor/bw-monitor.sh
#恢复自动测速模式(使用真实带宽)
sudo sed -i '/function get_bandwidth_speed/,+5d' /opt/bw-monitor/bw-monitor.sh
sudo sed -i '/main() {/i get_bandwidth_speed() {\n local result\n result=$($SPEEDTEST --simple)\n if [[ $? -eq 0 ]]; then\n local down\n down=$(echo "$result" | grep '\''Download'\'' | awk '\''{print $2}'\'')\n echo "$down"\n else\n log "[ERROR] Speedtest 失败"\n exit 1\n fi\n}' /opt/bw-monitor/bw-monitor.sh
sudo /opt/bw-monitor/bw-monitor.sh
命令无反馈,手动安装依赖
安装
speedtest-cli
:sudo apt update && sudo apt install speedtest-cli
安装
jq
:sudo apt install jq
安装
mutt
:sudo apt install mutt
安装
bc
:sudo apt install bc
安装
curl
:sudo apt install curl