Skip to content

v2.0.0

Choose a tag to compare

@github-actions github-actions released this 08 Jun 03:34
· 97 commits to main since this release

BaiduPCS-Rust v2.0.0 发行说明

发布日期:2026-06-08


🎯 版本说明

v2.0.0 是引入多账号支持的重大版本,版本号从 v1.14.1 跃升至 v2.0.0。多账号涉及任务归属、数据隔离与资源调度的架构级改动,按语义化版本属于不兼容的大版本升级,升级风险高于以往小版本,请务必先阅读「升级前必读」。

  • 核心新功能:多账号独立管理(添加 / 切换 / 删除)、按 owner_uid 的任务归属与数据隔离、实时资源配额调度(BudgetScheduler)
  • 稳定性:启动期自动修复 + 迁移前完整备份(任何破坏性操作之前)、全局只读保护兜底、断线自适应退避重连
  • 通用修复:下载取链 errno=8002 临时风控阶梯重试、filemetas 按路径解析 fs_id、创建即持久化下载任务

⚠️ 本版本会改动后端数据(SQLite 新增 owner_uid 列、.meta / 历史回填、session.json 改名迁移)。升级前请务必备份,详见下方说明。


⚠️ 升级前必读

升级前请先备份后端数据目录

升级到 v2.0.0 前,请先手动备份后端数据目录:

  • backend/config/(含 baidu-pcs.dbaccounts.jsonsession.jsonautobackup_configs.json
  • backend/wal/(任务状态 .meta

Docker 用户备份挂载的 data 卷即可。万一升级异常,恢复这两个目录即可回到升级前状态。

除手动备份外,后端在首次启动 2.0.0 且检测到既有数据时,会在任何破坏性迁移之前自动做一份完整备份到 config/backups/pre_migration_<时间戳>/(详见「启动期自动修复 + 迁移前完整备份」一节),作为额外保险。

降级提示

如需回退到旧版本,请先恢复升级前备份的 config/wal/ 目录,再启动旧版本;不建议直接用 2.0.0 升级后的数据目录启动旧版本。

原因:2.0.0 会改动数据(SQLite 新增 owner_uid 列、.meta / 历史回填、session.json 改名迁移),旧版本对这些改动的兼容性无法保证;且旧版本为单账号,会把多账号历史混在一起显示。若已无升级前备份,回退后至少需要重新登录

📌 自定义 DB 路径用户注意:若你在 config/app.toml[persistence].db_path 把数据库放到了 config/ 之外,则备份 / 还原 config/wal/ 并不包含该数据库文件——请额外备份 / 还原该真实 DB 文件(含其 -wal / -shm 边车文件)。系统的自动迁移前备份会按 db_path 复制真实 DB 到备份目录,但手动恢复时需把它放回原自定义位置。


✨ 多账号独立任务管理

支持添加 / 切换 / 删除多个百度账号,每个账号拥有独立的客户端实例(BDUSS / Cookie / 会话)与任务队列。下载 / 上传 / 转存 / 自动备份 / 离线下载任务均按 owner_uid 归属与隔离。

实现要点:

  • 数据隔离与归属:所有任务按 owner_uid 归属;删除账号时按 owner_uid 精确清理该账号的本地任务与历史,不误伤其他账号。
  • 跨账号聚合:聚合列表按 id 去重;历史回退路由按 owner_uid + task_type 精确匹配,避免跨账号 / 跨类型误删。
  • 并发安全收口:修复账号切换 / 操作备份任务后的死锁,以及父任务永久卡在 Transferring 的问题;统一收口 uploader 跨 await 持有 DashMap 锁的写法,消除多账号并发下的死锁。
  • 持久化迁移:单账号(session.json)→ 多账号(accounts.json)自动迁移,配套 SQLite schema 升级与 .meta / 历史回填(见下方迁移与备份说明)。

✨ 账号切换器与账号管理面板

  • 顶部新增账号切换器,一键在已登录账号间切换。
  • 设置页新增账号管理面板,集中管理(添加 / 切换 / 删除)账号。

✨ 实时资源配额(BudgetScheduler)

多账号同时下载时,机器总线程数有限,需要在账号之间公平分配。新增 BudgetScheduler 负责实时配额调度:

  • 按会员权重分配:机器总线程 M 按会员权重(普通 : VIP : SVIP = 1 : 3 : 5)在账号间分配,每个账号实时展示「保底 base / 上限 vip_cap」两条水位。
  • 自动按等级推荐:按 VIP 等级取线程上限(普通会员 10 / 超级会员 15),并同时受机器总线程与会员权重共同约束——推荐值是天花板,实际可用线程由总线程 + 权重共同决定。
  • 配额面板真实值:资源配额面板显示后端真实生效值与实际可用线程(不再写死推荐值),界面与实际调度一致。
  • 公平调度:优先级信号量(priority semaphore)公平调度各账号的分片并发。

✨ 启动期自动修复 + 迁移前完整备份

为了让单账号 → 多账号的迁移对普通用户无感,后端启动时按以下流程自动处理,只有在确实无法自动恢复时才进入只读保护:

启动
  ↓
迁移前完整备份(首次 2.0.0 启动且有既有数据时,做且仅做一次)
  ↓
运行迁移矩阵(session.json→accounts.json / SQLite ALTER / .meta 回填)
  ↓
失败?
  ├─ 临时锁 / 占用(database is locked/busy)→ 短退避自动重试(200ms→1s,最多 3 次)
  └─ 不可判定 / 高风险(DB 损坏 / 无权限 / 磁盘满)→ 进入全局只读保护
  ↓
成功则正常启动(用户无感知)

迁移前完整备份

  • 时机:备份发生在任何破坏性操作之前——早于 session.json → session.json.migrated 改名、accounts.json 写入、SQLite ALTER TABLE.meta 回写、历史 owner_uid 回填。备份调用置于服务初始化的最前面,先于任何会写库的组件初始化,确保备份到的是升级前的原始数据。
  • 目标目录config/backups/pre_migration_<时间戳>/
  • 备份内容(存在才复制):
    • app.tomlsession.jsonsession.json.migratedaccounts.jsonaccounts.json.bakautobackup_configs.json
    • 真实数据库文件:按 AppConfig.persistence.db_path 取真实路径(不写死 config/baidu-pcs.db),并一并复制 -wal / -shm 边车文件
    • 整个 wal/ 目录(任务状态 .meta
  • 触发判据:仅当 config/backups/尚无任何有效 pre_migration_* 备份(即本数据目录首次在 2.0.0 启动)且存在既有数据db / session.json / accounts.json 任一存在)时备份一次;之后每次启动因已存在有效备份而跳过,不会堆积。全新安装无既有数据则不备份。
  • 完成标记(manifest):备份成功复制内容后,会在备份目录写入 backup_manifest.json(记录完成时间、真实 DB / WAL 路径、实际复制清单 copied,以及关键文件清单 required)。只有带该 manifest 的目录才被认作有效备份——若仅创建了目录但复制失败 / 不完整(未写 manifest),下次启动不会误以为已备份,而会重新备份,避免「空壳备份」。
  • 关键文件校验(required:manifest 的 required 记录本次按既有数据应当包含的关键项(源端存在才计入):真实 DB 及其 -wal / -shm 边车(-wal 可能含尚未 checkpoint 的数据)、session.jsonaccounts.json、以及 wal/ 任务目录。启动判定有效备份时不仅看 manifest 存在,还会逐项确认这些项真实存在于备份目录;任一缺失即视为无效备份并重做。损坏 / 半写入的 manifest(读取或 JSON 解析失败)一律判为无效;旧版备份(manifest 无 required 字段)按「存在即有效」向后兼容、不会失效。
  • wal/ 内容完整性wal/ 目录必须完整复制——复制时若有任一文件复制 / 读取 / 遍历失败,整次迁移前备份即视为失败(不写 manifest、下次启动重做),不会留下「目录在但内容残缺」的假备份。manifest 另记 wal_fileswal/ 下各文件的相对路径清单),启动校验时逐项核对备份目录内对应文件是否存在,既能识别「数量被删少」也能识别「具体文件被删 / 替换但数量不变」。
  • 失败处理:单个文件复制失败仅告警、跳过;若一项都没复制成功或 manifest 写入失败则视为备份失败(不写标记)。备份失败不阻塞启动;若随后真实破坏性写入失败,会进入只读保护,用户仍可用升级前的手动备份还原。

临时错误自动重试

迁移命中临时性的 database is locked / database is busy(含 SQLITE_BUSY / SQLITE_LOCKED)时,按 200ms → 1s 退避自动重试,最多 3 次;缺列 / 重复列 / 表不存在 / 单账号 owner_uid 回填等情况已由迁移矩阵的幂等守卫吸收,不会误触发只读。


✨ 数据安全兜底·全局只读保护模式

只读模式是最后兜底,正常运行(迁移成功)时用户完全感知不到它,不会影响任何账号的下载 / 上传 / 转存。

  • 触发条件:仅当启动期「单账号 → 多账号」迁移在自动修复 + 重试都失败后,或关键持久化出现不可判定 / 高风险错误(DB 损坏 / 无权限 / 磁盘满)时,才自动置位。

  • 行为:全局拦截所有写操作(POST/PUT/DELETE/PATCH),读取 / 历史照常可用,避免数据已可能损坏时继续写入扩大不一致。

  • 诊断:进入只读前记录明确原因(failed_step / last_error / suggestion),以 info 级日志打印,供后端运维排查(不向用户暴露 migration / owner_uid / SQLite 等术语)。

  • 用户提示(自助恢复,无需联系开发者)

    服务端检测到数据异常,已进入只读保护模式以避免数据损坏。请先重启后端再次尝试自动修复;若重启后仍未恢复,请还原升级前备份的 config/wal/ 目录后重启;系统也会在升级迁移前自动备份到 config/backups/pre_migration_<时间戳>/

文案只承诺「再次尝试自动修复」,不承诺一定修复成功——遇到 DB 真损坏等持久问题时,用户可按提示还原升级前备份并回退版本。


✨ 断线自适应退避重连

后端临时不可达时,下载 / 上传页按阶梯退避重试轮询,0 B/s 显示「计算中」,避免一次轮询失败就清空任务列表、进而把自适应轮询直接停掉。下载页与上传页行为对齐:失败时保留现有列表,维持 active 状态以便退避重试继续。


🐛 问题修复(与多账号无关的通用项)

  • 🐛 下载取链 errno=8002 临时风控:命中风控时按阶梯式重试,提升弱网 / 风控下的成功率。
  • 🐛 filemetas 按路径查询:改用 xpan/file list 解析 fs_id,规避按路径查 filemetas 的不稳定。
  • 🐛 创建即持久化下载任务:任务创建时即落盘,重启后保留终态失败任务(不再丢失失败记录)。

🔧 升级说明

Docker 用户

# 升级前先备份挂载的 data 卷(强烈建议)

# 拉取指定版本镜像
docker pull komorebicarry/baidupcs-rust:v2.0.0

# 或使用 latest 标签
docker pull komorebicarry/baidupcs-rust:latest

# 重启容器
docker-compose down && docker-compose up -d

二进制用户

升级前先备份 backend/config/backend/wal/,再从 Releases 页面下载对应平台的二进制文件,替换原有可执行文件后重启服务。

配置与数据

  • 升级时后端会自动完成单账号 → 多账号的数据迁移(session.jsonaccounts.json、SQLite 新增 owner_uid 列、.meta / 历史回填),并在迁移前自动备份到 config/backups/pre_migration_<时间戳>/,正常情况下用户无感知。
  • 迁移成功后无需任何手动操作。若启动后界面提示「只读保护模式」,请按提示先重启后端再次尝试自动修复;仍未恢复时还原升级前备份的 config/wal/ 目录后重启。
  • 默认端口仍为 18888,不影响现有反向代理 / 防火墙 / 书签。

📁 下载

平台 文件名
Windows (x86_64) BaiduPCS-Rust-v2.0.0-windows-x86_64.zip
Linux (x86_64) BaiduPCS-Rust-v2.0.0-linux-x86_64.tar.gz
Linux (ARM64) BaiduPCS-Rust-v2.0.0-linux-aarch64.tar.gz
macOS (x86_64) BaiduPCS-Rust-v2.0.0-macos-x86_64.tar.gz
macOS (ARM64) BaiduPCS-Rust-v2.0.0-macos-aarch64.tar.gz
Docker 镜像 BaiduPCS-Rust-v2.0.0-docker.tar.gz

完整更新日志:参见项目根目录的 CHANGELOG.md
问题反馈:欢迎通过 GitHub Issues 进行反馈