Last active
July 1, 2025 07:46
-
-
Save yumin9822/5f4fda9cdb6a167464f771c7929ae934 to your computer and use it in GitHub Desktop.
qbittorrent
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# qBittorrent-nox 统一安装/升降级脚本 | |
# 自动检测系统状态并进行相应的安装或升降级操作 | |
# 检查是否为root用户 | |
if [ "$EUID" -ne 0 ]; then | |
echo "请以root用户运行此脚本" | |
exit 1 | |
fi | |
# 检查CPU架构并映射到对应的二进制文件名 | |
arch_raw=`uname -m` | |
case $arch_raw in | |
"x86_64") | |
arch="x86_64" | |
;; | |
"i386"|"i686") | |
arch="x86" | |
;; | |
"aarch64"|"arm64") | |
arch="aarch64" | |
;; | |
"armv7l"|"armv7") | |
arch="armv7" | |
;; | |
"arm") | |
arch="armhf" | |
;; | |
"riscv64") | |
arch="riscv64" | |
;; | |
*) | |
echo "CPU架构 $arch_raw 不支持,退出脚本" | |
echo "支持的架构: x86_64, i386/i686, aarch64/arm64, armv7l/armv7, arm, riscv64" | |
exit 1 | |
;; | |
esac | |
echo "检测到CPU架构: $arch_raw -> 使用二进制: $arch" | |
# 检测当前安装的qBittorrent版本 | |
echo "" | |
echo "检测当前系统qBittorrent状态..." | |
qb_binary_path="/usr/bin/qbittorrent-nox" | |
current_version="" | |
is_installed=false | |
if [ -f "$qb_binary_path" ]; then | |
# 尝试获取当前版本 | |
current_version=$($qb_binary_path --version 2>/dev/null | grep -i "qbittorrent" | sed 's/.*[qQ][bB]ittorrent[^0-9]*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/') | |
if [ -n "$current_version" ]; then | |
echo "检测到已安装的qBittorrent版本: $current_version" | |
is_installed=true | |
else | |
echo "检测到qBittorrent二进制文件,但无法获取版本信息" | |
current_version="unknown" | |
is_installed=true | |
fi | |
else | |
echo "未检测到已安装的qBittorrent" | |
is_installed=false | |
fi | |
# 检查systemd服务是否存在 | |
service_exists=false | |
if [ -f "/etc/systemd/system/qbittorrent-nox.service" ]; then | |
service_exists=true | |
fi | |
# 根据检测结果确定操作模式 | |
if [ "$is_installed" = true ]; then | |
echo "" | |
echo "==========================================" | |
echo "系统检测到已安装的qBittorrent" | |
echo "当前版本: $current_version" | |
echo "将进入升降级模式" | |
echo "==========================================" | |
operation_mode="upgrade" | |
else | |
echo "" | |
echo "==========================================" | |
echo "系统未检测到qBittorrent安装" | |
echo "将进入全新安装模式" | |
echo "==========================================" | |
operation_mode="install" | |
fi | |
# 如果是全新安装,需要配置端口和密码 | |
if [ "$operation_mode" = "install" ]; then | |
echo "" | |
echo "配置qBittorrent参数..." | |
echo "Please set qBittorrent server port:" | |
read -t 30 -p "(Default: 8080):" QB_PORT | |
if [ "$QB_PORT" = "" ]; then | |
QB_PORT="8080" | |
fi | |
echo "qBittorrent server port is: $QB_PORT" | |
echo "Please set qBittorrent web admin password:" | |
read -t 30 -p "(Default: qbadmin):" password | |
if [ "$password" = "" ]; then | |
password="qbadmin" | |
fi | |
echo "qBittorrent web admin password is: $password" | |
fi | |
# 版本选择方式 | |
echo "" | |
echo "请选择版本安装方式:" | |
echo "1) 从预定义版本中选择" | |
echo "2) 手动输入qBittorrent和libtorrent版本" | |
echo "3) 安装最新版本 (自动从GitHub获取)" | |
read -p "请输入选择 (1, 2, or 3): " install_method | |
case $install_method in | |
1) | |
# 预定义版本选择 | |
echo "请选择版本 (qBittorrent版本 - libtorrent版本):" | |
options=("qBittorrent 4.3.9 - libtorrent-v1.2.15" "qBittorrent 4.3.9 - libtorrent-v2.0.5" "qBittorrent 4.4.5 - libtorrent-v1.2.18" "qBittorrent 4.4.5 - libtorrent-v2.0.8" "qBittorrent 4.5.5 - libtorrent-v1.2.19" "qBittorrent 4.5.5 - libtorrent-v2.0.9" "qBittorrent 4.6.3 - libtorrent-v1.2.19" "qBittorrent 4.6.3 - libtorrent-v2.0.9" "qBittorrent 4.6.7 - libtorrent-v2.0.10") | |
select opt in "${options[@]}" | |
do | |
case $opt in | |
"qBittorrent 4.3.9 - libtorrent-v1.2.15") | |
qBver=4.3.9 && libver=1.2.15; break | |
;; | |
"qBittorrent 4.3.9 - libtorrent-v2.0.5") | |
qBver=4.3.9 && libver=2.0.5; break | |
;; | |
"qBittorrent 4.4.5 - libtorrent-v1.2.18") | |
qBver=4.4.5 && libver=1.2.18; break | |
;; | |
"qBittorrent 4.4.5 - libtorrent-v2.0.8") | |
qBver=4.4.5 && libver=2.0.8; break | |
;; | |
"qBittorrent 4.5.5 - libtorrent-v1.2.19") | |
qBver=4.5.5 && libver=1.2.19; break | |
;; | |
"qBittorrent 4.5.5 - libtorrent-v2.0.9") | |
qBver=4.5.5 && libver=2.0.9; break | |
;; | |
"qBittorrent 4.6.3 - libtorrent-v1.2.19") | |
qBver=4.6.3 && libver=1.2.19; break | |
;; | |
"qBittorrent 4.6.3 - libtorrent-v2.0.9") | |
qBver=4.6.3 && libver=2.0.9; break | |
;; | |
"qBittorrent 4.6.7 - libtorrent-v2.0.10") | |
qBver=4.6.7 && libver=2.0.10; break | |
;; | |
*) echo "请选择有效的版本"; | |
esac | |
done | |
;; | |
2) | |
# 手动输入版本 | |
echo "" | |
echo "手动版本输入模式" | |
echo "你可以在此处查看所有可用版本:" | |
echo "https://github.com/userdocs/qbittorrent-nox-static/releases" | |
echo "" | |
echo "常见qBittorrent版本: 4.3.9, 4.4.5, 4.5.5, 4.6.3, 4.6.7, 4.6.8, 5.1.1" | |
read -p "请输入qBittorrent版本 (例如: 4.6.7): " qBver | |
if [ -z "$qBver" ]; then | |
echo "错误: qBittorrent版本不能为空" | |
exit 1 | |
fi | |
echo "常见libtorrent版本: 1.2.15, 1.2.18, 1.2.19, 2.0.5, 2.0.8, 2.0.9, 2.0.10, 2.0.11" | |
read -p "请输入libtorrent版本 (例如: 2.0.10): " libver | |
if [ -z "$libver" ]; then | |
echo "错误: libtorrent版本不能为空" | |
exit 1 | |
fi | |
echo "选择的版本: qBittorrent $qBver - libtorrent v$libver" | |
read -p "确认${operation_mode}? (y/N): " confirm | |
if [[ ! $confirm =~ ^[Yy]$ ]]; then | |
echo "操作已取消" | |
exit 0 | |
fi | |
;; | |
3) | |
# 获取最新版本 | |
echo "" | |
echo "从GitHub获取最新版本信息..." | |
# 检查是否有必要的工具 | |
if ! command -v wget > /dev/null && ! command -v curl > /dev/null; then | |
echo "错误: wget和curl都不可用,请安装其中一个" | |
exit 1 | |
fi | |
# 尝试获取版本信息 | |
if command -v wget > /dev/null; then | |
version_json=$(wget -qO- "https://github.com/userdocs/qbittorrent-nox-static/releases/latest/download/dependency-version.json" 2>/dev/null) | |
else | |
version_json=$(curl -s "https://github.com/userdocs/qbittorrent-nox-static/releases/latest/download/dependency-version.json" 2>/dev/null) | |
fi | |
if [ -z "$version_json" ]; then | |
echo "错误: 无法从GitHub获取版本信息" | |
echo "请检查网络连接或稍后重试" | |
exit 1 | |
fi | |
# 解析JSON获取版本号 | |
qBver=$(echo "$version_json" | grep '"qbittorrent"' | sed 's/.*"qbittorrent"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/') | |
libver=$(echo "$version_json" | grep '"libtorrent_2_0"' | sed 's/.*"libtorrent_2_0"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/') | |
if [ -z "$qBver" ] || [ -z "$libver" ]; then | |
echo "错误: 无法解析版本信息" | |
echo "原始响应: $version_json" | |
exit 1 | |
fi | |
echo "找到的最新版本:" | |
echo "- qBittorrent: $qBver" | |
echo "- libtorrent: $libver" | |
# 检查是否需要升降级 | |
if [ "$operation_mode" = "upgrade" ] && [ "$current_version" = "$qBver" ]; then | |
echo "" | |
echo "当前版本已经是最新版本 ($current_version)" | |
read -p "是否强制重新安装? (y/N): " force_install | |
if [[ ! $force_install =~ ^[Yy]$ ]]; then | |
echo "操作已取消" | |
exit 0 | |
fi | |
fi | |
echo "" | |
read -p "确认${operation_mode}到最新版本? (y/N): " confirm | |
if [[ ! $confirm =~ ^[Yy]$ ]]; then | |
echo "操作已取消" | |
exit 0 | |
fi | |
;; | |
*) | |
echo "无效选择,退出" | |
exit 1 | |
;; | |
esac | |
# 检查版本是否相同(仅升降级模式) | |
if [ "$operation_mode" = "upgrade" ] && [ "$current_version" = "$qBver" ] && [ "$install_method" != "3" ]; then | |
echo "" | |
echo "警告: 目标版本 ($qBver) 与当前版本 ($current_version) 相同" | |
read -p "是否继续? (y/N): " continue_same | |
if [[ ! $continue_same =~ ^[Yy]$ ]]; then | |
echo "操作已取消" | |
exit 0 | |
fi | |
fi | |
echo "" | |
echo "开始${operation_mode}: qBittorrent $qBver with libtorrent v$libver..." | |
# 构建下载URL | |
download_url="https://github.com/userdocs/qbittorrent-nox-static/releases/download/release-${qBver}_v${libver}/${arch}-qbittorrent-nox" | |
echo "下载URL: $download_url" | |
# 下载二进制文件到临时位置 | |
temp_binary="/tmp/qbittorrent-nox-${qBver}" | |
echo "下载中..." | |
if ! wget "$download_url" -O "$temp_binary"; then | |
echo "错误: 下载qBittorrent二进制文件失败" | |
echo "请检查版本组合是否存在: https://github.com/userdocs/qbittorrent-nox-static/releases" | |
exit 1 | |
fi | |
chmod +x "$temp_binary" | |
# 验证下载的二进制文件 | |
echo "验证下载的二进制文件..." | |
downloaded_version=$($temp_binary --version 2>/dev/null | grep -i "qbittorrent" | sed 's/.*[qQ][bB]ittorrent[^0-9]*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/') | |
if [ -z "$downloaded_version" ]; then | |
echo "警告: 无法验证下载的二进制文件版本" | |
else | |
echo "下载的版本: $downloaded_version" | |
if [ "$downloaded_version" != "$qBver" ]; then | |
echo "警告: 下载的版本 ($downloaded_version) 与预期版本 ($qBver) 不匹配" | |
read -p "是否继续安装? (y/N): " continue_mismatch | |
if [[ ! $continue_mismatch =~ ^[Yy]$ ]]; then | |
echo "操作已取消" | |
rm -f "$temp_binary" | |
exit 0 | |
fi | |
fi | |
fi | |
# 停止qBittorrent服务 | |
echo "" | |
echo "停止qBittorrent服务..." | |
systemctl stop qbittorrent-nox.service 2>/dev/null || true | |
# 等待进程完全停止 | |
echo "等待进程完全停止..." | |
sleep 3 | |
# 强制杀死残留进程 | |
if pgrep -i -f qbittorrent > /dev/null; then | |
echo "强制终止残留的qBittorrent进程..." | |
pkill -f qbittorrent | |
sleep 2 | |
fi | |
# 备份当前版本(仅升降级模式) | |
backup_name="" | |
if [ "$operation_mode" = "upgrade" ] && [ -f "$qb_binary_path" ]; then | |
if [ -n "$current_version" ] && [ "$current_version" != "unknown" ]; then | |
backup_name="/usr/bin/qbittorrent-nox-v${current_version}" | |
else | |
backup_name="/usr/bin/qbittorrent-nox-backup-$(date +%Y%m%d-%H%M%S)" | |
fi | |
echo "备份当前版本到: $backup_name" | |
mv "$qb_binary_path" "$backup_name" | |
if [ $? -eq 0 ]; then | |
echo "备份成功" | |
else | |
echo "错误: 备份失败" | |
rm -f "$temp_binary" | |
exit 1 | |
fi | |
elif [ "$operation_mode" = "install" ] && [ -f "$qb_binary_path" ]; then | |
echo "备份现有二进制文件..." | |
mv "$qb_binary_path" "/usr/bin/qbittorrent-nox-old" | |
echo "旧二进制文件备份为: /usr/bin/qbittorrent-nox-old" | |
fi | |
# 安装新版本 | |
echo "安装新版本..." | |
mv "$temp_binary" "$qb_binary_path" | |
if [ $? -eq 0 ]; then | |
echo "新版本安装成功" | |
else | |
echo "错误: 安装新版本失败" | |
# 尝试恢复备份 | |
if [ -n "$backup_name" ] && [ -f "$backup_name" ]; then | |
echo "尝试恢复备份..." | |
mv "$backup_name" "$qb_binary_path" | |
fi | |
exit 1 | |
fi | |
# 创建或更新systemd服务文件(全新安装或服务文件不存在时) | |
if [ "$operation_mode" = "install" ] || [ "$service_exists" = false ]; then | |
echo "创建systemd服务..." | |
cat <<-EOF >/etc/systemd/system/qbittorrent-nox.service | |
[Unit] | |
Description=qBittorrent-nox | |
After=network.target | |
[Service] | |
User=root | |
Type=forking | |
RemainAfterExit=yes | |
ExecStart=/usr/bin/qbittorrent-nox -d --webui-port="${QB_PORT:-8080}" | |
[Install] | |
WantedBy=multi-user.target | |
EOF | |
# 重载systemd配置 | |
systemctl daemon-reload | |
systemctl enable qbittorrent-nox | |
fi | |
# 仅在全新安装时配置qBittorrent(升降级模式下保持原有配置不变) | |
if [ "$operation_mode" = "install" ]; then | |
echo "配置qBittorrent..." | |
# 创建配置目录 | |
mkdir -p /root/.config/qBittorrent | |
# 检查是否已存在配置文件 | |
if [ -f "/root/.config/qBittorrent/qBittorrent.conf" ]; then | |
echo "检测到现有配置文件,保持原有配置不变" | |
else | |
echo "创建新的配置文件..." | |
# 下载密码生成工具并生成加密密码 | |
wget "https://fastly.jsdelivr.net/gh/yumin9822/Seedbox-Components@main/Torrent%20Clients/qBittorrent/${arch}/qb_password_gen" -O /tmp/qb_password_gen && chmod +x /tmp/qb_password_gen | |
PBKDF2password=$(/tmp/qb_password_gen $password) | |
# 创建配置文件 | |
cat <<-EOF >/root/.config/qBittorrent/qBittorrent.conf | |
[BitTorrent] | |
Session\CheckingMemUsageSize=512 | |
Session\ValidateHTTPSTrackerCertificate=false | |
[LegalNotice] | |
Accepted=true | |
[Network] | |
Cookies=@Invalid() | |
[Preferences] | |
Connection\PortRangeMin=45000 | |
Bittorrent\MaxConnecs=1024 | |
Bittorrent\MaxConnecsPerTorrent=16 | |
Bittorrent\MaxUploads=-1 | |
Bittorrent\MaxUploadsPerTorrent=-1 | |
WebUI\CSRFProtection=false | |
Queueing\QueueingEnabled=false | |
WebUI\LocalHostAuth=false | |
WebUI\Password_PBKDF2="@ByteArray($PBKDF2password)" | |
WebUI\Port=${QB_PORT} | |
WebUI\Username=admin | |
EOF | |
# 清理临时文件 | |
rm -f /tmp/qb_password_gen | |
fi | |
else | |
echo "升降级模式:保持现有配置文件不变" | |
fi | |
# 启动qBittorrent服务 | |
echo "启动qBittorrent服务..." | |
systemctl start qbittorrent-nox.service | |
# 检查服务状态 | |
sleep 3 | |
if systemctl is-active --quiet qbittorrent-nox.service; then | |
echo "qBittorrent服务启动成功" | |
else | |
echo "警告: qBittorrent服务启动可能失败" | |
echo "请检查服务状态: systemctl status qbittorrent-nox" | |
fi | |
# 验证安装/升降级结果 | |
echo "" | |
echo "验证操作结果..." | |
new_version=$($qb_binary_path --version 2>/dev/null | grep -i "qbittorrent" | sed 's/.*[qQ][bB]ittorrent[^0-9]*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/') | |
# 获取公网IP(仅全新安装时) | |
if [ "$operation_mode" = "install" ]; then | |
IPADDRESS=$(wget -4qO- ifconfig.me/ip 2>/dev/null) || IPADDRESS=$(wget -4qO- ip.sb 2>/dev/null) || IPADDRESS="YOUR_SERVER_IP" | |
fi | |
echo "======================================" | |
if [ "$operation_mode" = "upgrade" ]; then | |
echo "qBittorrent升降级完成!" | |
echo "- 原版本: $current_version" | |
echo "- 新版本: $new_version" | |
echo "- libtorrent: v$libver" | |
if [ -n "$backup_name" ]; then | |
echo "- 备份位置: $backup_name" | |
fi | |
else | |
echo "qBittorrent安装完成!" | |
echo "- qBittorrent: $new_version" | |
echo "- libtorrent: v$libver" | |
echo "- Web界面: http://${IPADDRESS}:${QB_PORT}" | |
echo "- 用户名: admin" | |
echo "- 密码: ${password}" | |
fi | |
echo "" | |
echo "服务管理命令:" | |
echo "- 启动服务: systemctl start qbittorrent-nox" | |
echo "- 停止服务: systemctl stop qbittorrent-nox" | |
echo "- 查看状态: systemctl status qbittorrent-nox" | |
echo "- 查看日志: journalctl -u qbittorrent-nox -f" | |
echo "" | |
if [ "$operation_mode" = "upgrade" ] && [ -n "$backup_name" ]; then | |
echo "如果升降级后出现问题,可以恢复备份:" | |
echo " systemctl stop qbittorrent-nox" | |
echo " mv $backup_name $qb_binary_path" | |
echo " systemctl start qbittorrent-nox" | |
echo "" | |
fi | |
if [ "$operation_mode" = "install" ]; then | |
echo "如果无法从外网访问Web界面,请尝试:" | |
echo " iptables -I INPUT -p tcp --dport ${QB_PORT} -j ACCEPT" | |
echo " # 或者关闭防火墙 (请谨慎操作):" | |
echo " # iptables -F && iptables-save > /etc/iptables/rules.v4" | |
echo " # ufw disable" | |
fi | |
echo "======================================" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name qbittorrent 状态栏显示数量和大小 | |
// @name:en show counts and sizes of selected for qBittorrent | |
// @namespace localhost | |
// @version 2024-01-31 | |
// @description 在 webUI 状态栏显示选中种子信息 | |
// @description:en show counts and sizes of selected torrents. | |
// @author flashlab | |
// @match http://127.0.0.1:8080/ | |
// @match *:*/* | |
// @icon https://www.qbittorrent.org/favicon.ico | |
// @license MIT | |
// @grant unsafeWindow | |
// @run-at document-end | |
// @downloadURL https://update.greasyfork.org/scripts/484895/qbittorrent%20%E7%8A%B6%E6%80%81%E6%A0%8F%E6%98%BE%E7%A4%BA%E6%95%B0%E9%87%8F%E5%92%8C%E5%A4%A7%E5%B0%8F.user.js | |
// @updateURL https://update.greasyfork.org/scripts/484895/qbittorrent%20%E7%8A%B6%E6%80%81%E6%A0%8F%E6%98%BE%E7%A4%BA%E6%95%B0%E9%87%8F%E5%92%8C%E5%A4%A7%E5%B0%8F.meta.js | |
// ==/UserScript== | |
/* globals torrentsTable */ | |
(function() { | |
'use strict'; | |
window.addEventListener('load', function () { | |
const states= ['size', 'total_size', 'unique_size', 'uploaded']; | |
var statusKey = states[0]; | |
// update info | |
function updateSelected() { | |
const statusTd = document.getElementById("selectedStatus"); | |
if (!statusTd) return; | |
const selectedRows = torrentsTable.selectedRowsIds(); | |
const rows = torrentsTable.getFilteredAndSortedRows(); | |
var counts = 0; | |
var sizes; | |
var readableSize; | |
if (statusKey.startsWith("unique")) { | |
const rawSizes = selectedRows.map(hash => rows[hash].full_data.size); | |
sizes = [...new Set(rawSizes)].reduce((sum, size) => { | |
++counts; | |
return (sum + size) | |
}, 0) | |
} else { | |
counts = selectedRows.length; | |
sizes = selectedRows.reduce( | |
(sum, hash) => rows[hash].full_data[statusKey] + sum, 0 | |
) | |
} | |
readableSize = unsafeWindow.qBittorrent.Misc.friendlyUnit(sizes); | |
statusTd.textContent = `${readableSize} ${statusKey} of ${counts}` | |
statusTd.title = `${sizes} bytes` | |
} | |
(function main() { | |
let statusTd = document.getElementById("selectedStatus"); | |
if (statusTd) return; | |
const footerow = document.querySelector("#desktopFooter > table > tbody > tr"); | |
const bar = document.createElement("td"); | |
bar.className = "statusBarSeparator"; | |
footerow.insertAdjacentElement("afterbegin", bar); | |
const info = document.createElement("td"); | |
info.id = "selectedStatus"; | |
info.textContent = "点击切换显示方式" | |
info.style.cursor = "pointer"; | |
statusTd = footerow.insertAdjacentElement("afterbegin", info); | |
// switch event | |
statusTd.onclick = (() => { | |
let i = 0; | |
return function(){ | |
i = ++i%states.length; | |
statusKey = states[i]; | |
updateSelected(); | |
}; | |
})(); | |
if (typeof torrentsTable == 'undefined' || !torrentsTable.onSelectedRowChanged || torrentsTable.customOnSelectedRowChanged) return | |
torrentsTable.customOnSelectedRowChanged = torrentsTable.onSelectedRowChanged; | |
torrentsTable.onSelectedRowChanged = () => { | |
torrentsTable.customOnSelectedRowChanged(); | |
updateSelected() | |
} | |
torrentsTable.customSelectAll = torrentsTable.selectAll; | |
torrentsTable.selectAll = () => { | |
torrentsTable.customSelectAll(); | |
updateSelected() | |
} | |
})(); | |
}) | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment