# 官方资源拉取用户指南 本文档描述当前可用的官方日服资源拉取流程。 默认平台: - `Windows` - `Android` 不包含: - `iOS` - `macOS` - `bluearchive.cafe` 或其他镜像域名 - 任何本地客户端目录 - 任何已安装的官方启动器或 Windows 客户端 ## 0. 快速入口 查看命令参数: ```bash cargo run -p bat-infrastructure --bin bat -- --help ``` 构建生产 binary: ```bash cargo build --release -p bat-infrastructure --bin bat ``` 使用 release binary 做一次 dry-run: ```bash target/release/bat \ --auto-discover \ --dry-run ``` 常驻自动更新: ```bash target/release/bat \ --auto-discover \ --watch ``` 默认资源输出目录是 `./bat-resources`,默认后台状态目录是 `/tmp/bat-pid`。资源输出目录是发布根目录:非 dry-run 同步先写 `/.staging/`,校验完成后移动到 `/versions/`,再原子切换 `/current` symlink;生产读取方应读取 `current`。后台状态目录会保存 `bat.sock`、`bat.pid`、`bat-status.json`、`bat-daemon.log`、`bat-events.jsonl` 和短生命周期的 `bat-control.lock`;其中 `bat.sock` 是 live daemon 的 Unix socket JSON-RPC 控制通道,`bat-events.jsonl` 是带轮转的结构化 JSONL 事件日志,`bat-status.json` 保存最后成功时间、下次检查时间、最后错误摘要和当前下载进度,`bat-control.lock` 串行化 `status/stop/restart/reload/logs/refresh` 等控制命令。生产资源输出目录必须是独立目录;需要覆盖时用 `--output <资源目录>`,不要使用已有游戏客户端目录、官方启动器安装目录、人工维护资源目录,或开发机上的 `/home/wanye/D/BlueArchive`。 同步流程会拒绝危险输出目录、路径逃逸和现有 symlink 路径组件;下载目标、`.part`、manifest、snapshot、PID、status、log 和控制锁文件不会跟随 symlink,daemon 状态类文件默认以 `0600` 权限创建。 ## 0.1 本地代理 `bat` 默认会自动读取当前进程环境中的 curl 代理变量:`HTTPS_PROXY`、`https_proxy`、`ALL_PROXY`、`all_proxy`、`HTTP_PROXY`、`http_proxy`,并保留 `NO_PROXY` / `no_proxy`。同步开始时会输出一条 `proxy` 进度日志;`bat doctor` 也会显示当前代理解析结果。 **推荐:带凭据的代理优先用环境变量。** 如果代理 URL 里含有用户名/密码,优先通过标准代理环境变量配置,而不是命令行参数: ```bash HTTPS_PROXY=http://user:pass@127.0.0.1:7890 target/release/bat --auto-discover ``` 生产环境用 systemd 时,把该变量写进 `EnvironmentFile=`(建议 `0600`),凭据就不会进入 shell 历史、`ps`、进程 argv 或任何状态文件。这是配置带凭据代理最简单也最安全的方式。 也可以用 `--proxy` 参数手动指定(无凭据的本地代理用这个最方便): ```bash target/release/bat \ --auto-discover \ --proxy http://127.0.0.1:7890 ``` 明确关闭代理并直连: ```bash target/release/bat \ --auto-discover \ --no-proxy ``` 确认当前代理配置: ```bash target/release/bat doctor --proxy http://127.0.0.1:7890 ``` `--proxy auto` 会恢复默认环境变量自动检测;`--proxy none`、`--proxy direct`、`--proxy off` 和 `--proxy disabled` 等价于 `--no-proxy`。 **凭据处理**:无论用环境变量还是 `--proxy` 参数,代理凭据都不会以明文出现在世界可读的位置——日志和 `status` 输出中会脱敏;传给 curl 子进程时经 `ALL_PROXY` 环境变量而非 `--proxy` 参数,因此不落 curl 的 `/proc//cmdline`;`--daemon` 模式下代理凭据经环境变量下传后台子进程,不进入子进程 argv 或 `bat-status.json`,复用所需的凭据单独存于后台状态目录下的 `bat-proxy.secret`(`0600`),`clean-stable` 会在后台停止后清除它。后续 `restart` / `reload` 会复用同一代理配置;若该凭据文件已被清除,复用型 `restart` 会明确报错要求重新传入代理。 代理只影响 curl 传输层,资源 URL 仍必须是官方域名;不要把代理配置成镜像、转写或非官方资源来源。 ## 1. 当前流程 Linux 生产运行时链路只走官方日服 HTTP 资源,不安装、不启动、不依赖官方启动器二进制: 1. 显式执行 `--auto-discover`,通过官方 HTTP metadata 自动发现 `app-version`、`server-info` URL 和默认 `connection-group`。 2. 请求官方 `server-info`。 3. 生成 Windows + Android 的官方资源 discovery 端点。 4. 拉取 seed catalog,生成完整官方 pull plan。 5. dry-run 只输出 URL;非 dry-run 下载全部官方 URL 到 staging,验收完成后原子发布到 `current`。 `--auto-discover` 会下载官方 metadata,并按官方 manifest 临时获取 `resources.assets` 解析 `GameMainConfig`;旧 ZIP manifest 才会下载临时 game zip。该流程不会安装官方启动器,也不会执行官方启动器进程。`--launcher-bootstrap` 只是旧命名兼容别名,新流程不要再推荐使用。 ## 2. 可选 metadata 审计 如需单独审计官方 metadata API 和官方 ZIP 链路,可以手动运行: ```bash cargo run -p bat-infrastructure --example official_launcher_bootstrap -- \ --launcher-version 1.7.2 \ --manifest ``` 这一步会输出: - `game_latest_version` - `game_latest_file_path` - `primary_cdn` - `backup_cdn` - `manifest_url` - `manifest_source` - `manifest_file_count` 所有 URL 都应来自官方域名。 ## 3. 先做 dry-run 推荐开发和生产自动化的默认流程是显式打开 `--auto-discover`: ```bash cargo run -p bat-infrastructure --example official_pull_plan -- \ --auto-discover \ --output /tmp/bat-official-pull \ --dry-run ``` 如果你要复现某次已审计的 metadata snapshot,也可以显式传入官方 `server-info` 文件名: ```bash cargo run -p bat-infrastructure --example official_pull_plan -- \ --server-info-file r93_70_xxxxxxxxxxxxxxxxxxxx.json \ --connection-group Prod-Audit \ --app-version 1.70.0 \ --output /tmp/bat-official-pull \ --dry-run ``` 如果你已经把官方 `server-info` JSON 存成只读本地文件,也可以使用: ```bash cargo run -p bat-infrastructure --example official_pull_plan -- \ --server-info-path /path/to/server-info.json \ --connection-group Prod-Audit \ --app-version 1.70.0 \ --output /tmp/bat-official-pull \ --dry-run ``` 检查输出时,重点看: - `platforms=[Windows, Android]` - `discovery_url_count` 大于 0 - `content_url_count` 大于 0 - 不出现 `bluearchive.cafe` ## 4. 执行真实拉取 确认 dry-run 正常后,去掉 `--dry-run`: ```bash cargo run -p bat-infrastructure --example official_pull_plan -- \ --auto-discover \ --output /tmp/bat-official-pull ``` 程序会: - 只接受官方 URL - 下载完整官方资源集合 - 下载成功后在 release 目录维护 `official-download-manifest.json` - 已存在目标文件只有在本地下载清单中的 size 和 BLAKE3 校验通过时才会跳过;`.zip` 文件还必须通过 ZIP central directory / local header 结构校验 - `TableCatalog.bytes`、`BundlePackingInfo.bytes`、`MediaCatalog.bytes` 会用官方 `.hash` 做强校验;该 `.hash` 是 `xxHash32(seed=0)` 的十进制文本 - `catalog_*.hash` 是 Unity Addressables/SBP 写出的 catalog 变更标记,来源是 `HashingMethods.Calculate(json/bin catalog)` 生成的 `Hash128` 文本;它不是 seed catalog 的 `xxHash32` 规则,目前不作为 zip/JSON 内容强校验 - 存在 `.part` 临时文件时会尝试断点续传 - 新下载先写 `.part`,成功并通过必要校验后再替换为最终文件;如果断点续传后的 `.zip` 结构校验失败,会删除 `.part` 并重新全量下载 - 如果上一轮非 dry-run 已进入 staging 但未发布成功,下一轮会优先查找 `/official-version-state.json` 中同一 app version、bundle version 和 Addressables root 的失败版本;只有对应 `/.staging/` 仍存在、路径安全且 `versions/` 尚未发布时,才复用该 staging,并继续按 manifest 校验复用或重下单个 URL - 把结果发布到 `--output/current` ## 5. 自动更新检查 正式自动更新入口是 `bat`。它会保存上一次成功同步的 snapshot,下次运行时先自动发现当前官方 metadata,再和 snapshot 对比: - 每轮都会先拉取轻量官方 metadata 和 `.hash` marker。 - URL 没变但 `.hash` / marker 内容变更时,也会判定为需要更新。 - 即使远端 snapshot 未变化,只要 active release 没有任何当前 pull plan 的本地 manifest 条目或目标文件,也会按首次运行处理并执行全量拉取。 - 远端无变化时,默认执行 active release 中的 `official-download-manifest.json` audit。 - 本地文件缺失、路径不一致、size 不一致、BLAKE3 不一致或 ZIP 结构无效时,默认进入 repair 并重下必要文件。 - 官方 seed `.hash` 校验失败会让本轮失败,并清理对应本地 manifest 条目;下一轮会继续把这类文件视为需要 repair,而不是把失败产物当作健康缓存复用。 - curl 默认自动检测本地代理环境;也可以用 `--proxy ` 显式指定代理,或用 `--no-proxy` 强制直连。代理决策会进入 progress log、daemon log 和 `doctor` 诊断输出。 - curl 失败会按类型分类:403/404/普通 4xx 不重试,5xx、429、DNS、连接、超时、中断和网络类错误按尝试次数重试。 - 单个 URL 最终失败后会写入 `official-download-quarantine.json`,progress log、daemon status 和 `bat-events.jsonl` 会记录失败类型、HTTP 状态、是否可重试、尝试次数和 quarantine 状态。 - quarantine 项会跳过本轮发布并让同步失败,避免把不完整 staging 发布到 `current`;下一轮 repair/refresh 成功后会清理对应 quarantine 条目。 - 失败或中断后的 staging 不会无条件丢弃:如果 version-state 记录的失败版本和本轮远端元数据匹配,且 staging 目录仍安全存在,下一轮会复用该 staging;已通过 manifest 校验的文件会跳过,缺失、损坏、无 manifest 或官方 seed `.hash` 需要刷新的 URL 会重新下载。 - 旧 launcher 包或 `resources.assets` 下载路径使用官方 launcher CDN 配置,primary CDN 失败后会切换官方 backup CDN;资源 patch host 当前只使用 server-info 返回的官方 client-patch host,不猜测非官方镜像。 - 远端和本地都一致:单次模式输出 `update_status=up_to_date`,watch 模式默认静默并等待下次检查。 - 有远端变化或本地 repair:生成 pull plan,下载完整官方资源到 staging,成功后更新 snapshot 并原子发布到 `current`。 - 非 dry-run 会维护 `/official-version-state.json`:开始下载后写入 `in_progress_version`,发布成功后写入 `current_completed_version` 和 `previous_available_version`,失败或中断后写入 `failed_versions`。同一 app version、bundle version 和 Addressables root 的失败只保留最新一条;同一版本开始重新拉取或后续发布成功时会清理对应失败记录。重新拉取同一失败版本时会复用安全存在的失败 staging,不会因为 `publish_id` 变化从空目录重新开始。 - `--dry-run`:只报告本次是否会下载,不写 snapshot;如果 cache miss,也不会写入新的 bootstrap cache。 - `--dry-run --plan`:除更新判断外,还会解析 seed catalog 并打印完整下载 URL。 - 真实更新会输出 `downloaded_count`、`resumed_count`、`skipped_count`、`transferred_bytes`、`official_seed_hash_verified_count`。 - 校验报告分层输出 `official_seed_hash_verified_count`、`local_manifest_verified_count`、`addressables_marker_checked_count`、`unverified_marker_count`。 - 下载阶段复用同一套本地清单、ZIP 结构校验和 `.part` 续传逻辑;没有清单或校验不匹配的文件会重新下载。 资源同步状态文件默认分布如下: - `/current/official-sync-snapshot.json`:上一次成功同步的 v2 snapshot,包含 app version、connection group、bundle version、addressables root、endpoint URL、官方 seed `.hash` 内容、Addressables `catalog_*.hash` marker、launcher metadata 摘要和 `GameMainConfig` 摘要。 - `/official-bootstrap-cache.json`:`--auto-discover` 的 `GameMainConfig` 解析缓存。launcher metadata 未变时复用缓存;metadata 变化时才通过官方 HTTP 按 manifest 下载必要 `resources.assets` 或旧版 game zip 到临时目录解析。 - `/official-version-state.json`:资源发布根目录的持久版本状态,包含当前已完成版本、正在拉取版本、上一个可用版本和失败版本。 - `/current/official-download-manifest.json`:本地下载强校验清单,记录 URL、相对路径、size 和 BLAKE3。 - `/current/official-download-quarantine.json` 或当前 staging 下同名文件:下载最终失败的 URL 诊断记录,包含失败类型、HTTP 状态、是否可重试、尝试次数和最后错误。 先 dry-run: ```bash cargo run -p bat-infrastructure --bin bat -- \ --auto-discover \ --dry-run ``` 如果需要在 dry-run 阶段审阅完整下载 URL,加 `--plan`: ```bash cargo run -p bat-infrastructure --bin bat -- \ --auto-discover \ --dry-run \ --plan ``` 确认后执行真实更新: ```bash cargo run -p bat-infrastructure --bin bat -- \ --auto-discover ``` Rust 常驻更新模式默认每 1 小时执行一次检查,符合则静默,不符合则自动拉取/repair 并输出人类可读摘要;需要稳定 JSON report 时加 `--json`: ```bash cargo run -p bat-infrastructure --bin bat -- \ --auto-discover \ --watch ``` 后台自动运行使用 `--daemon`。它会启动一个脱离终端的 watch 子进程,资源默认写入 `./bat-resources`,后台控制和状态默认写入 `/tmp/bat-pid`: ```bash cargo run -p bat-infrastructure --bin bat -- \ --auto-discover \ --daemon cargo run -p bat-infrastructure --bin bat -- status cargo run -p bat-infrastructure --bin bat -- logs cargo run -p bat-infrastructure --bin bat -- restart cargo run -p bat-infrastructure --bin bat -- reload cargo run -p bat-infrastructure --bin bat -- stop ``` `status`、`stop`、`logs`、`reload` 和默认形态的 `refresh` 会优先连接 `bat.sock`,通过 Unix socket JSON-RPC 和 live daemon 通信;socket 不可用时,`status`、`stop` 会回退到 PID/状态文件兼容路径。`status` 会显示最后成功时间、下次检查时间、最后错误摘要、当前阶段、当前下载 URL 进度、版本状态摘要、最近历史失败版本和原因、文本日志路径、结构化日志路径和轮转日志路径;正在重新拉取同一版本时,对应旧失败不会作为当前历史失败摘要展示;人类输出不会把完整 `official-version-state.json` 内联打印成 JSON。控制命令会通过 `bat-control.lock` 做跨进程互斥,失效或损坏的控制锁会在下次控制命令或 `clean-stable` 时恢复。`restart` 会停止旧后台进程并按保存参数或显式参数重新启动;`reload` 在未显式传入同步参数时不会重启进程,而是唤醒或排队 watch 循环重新执行自动发现和强制刷新:空闲睡眠时立即执行,正在同步时等当前轮结束;如果显式传入 `--proxy` 或 `--no-proxy`,会按新代理配置重启后台进程。所有命令默认输出人类可读摘要,脚本集成时加 `--json`。 如果要把后台状态目录改到其他位置,使用 `--state-dir <目录>`: ```bash cargo run -p bat-infrastructure --bin bat -- \ --auto-discover \ --daemon \ --state-dir /tmp/bat-prod-pid cargo run -p bat-infrastructure --bin bat -- status --state-dir /tmp/bat-prod-pid cargo run -p bat-infrastructure --bin bat -- logs --state-dir /tmp/bat-prod-pid --tail 200 cargo run -p bat-infrastructure --bin bat -- stop --state-dir /tmp/bat-prod-pid ``` 常用手动维护命令: ```bash cargo run -p bat-infrastructure --bin bat -- refresh cargo run -p bat-infrastructure --bin bat -- refresh --force cargo run -p bat-infrastructure --bin bat -- verify cargo run -p bat-infrastructure --bin bat -- repair cargo run -p bat-infrastructure --bin bat -- doctor cargo run -p bat-infrastructure --bin bat -- clean-stable ``` - `refresh` 执行一次同步检查;`refresh --force` 强制刷新并重新匹配当前官方资源。 - 如果后台 daemon 正在运行,并且 `refresh` 没有显式指定另一套资源目录、server-info、connection-group、app-version、platforms、snapshot、curl、proxy 或 unzip 参数,`refresh` / `refresh --force` 会通过 RPC 唤醒或排队后台进程执行;否则作为一次性前台同步运行。一次性前台 `run/watch/refresh/repair` 如果要写入 live daemon 正在管理的同一资源目录,会返回 locked 错误;需要先 `stop` 或改用默认 `refresh` 走 RPC。 - `verify` 只读验证当前官方计划、本地 manifest size+BLAKE3、ZIP 结构,以及本地已有官方 seed `.bytes/.hash` 对的 xxHash32;资源缺失、远端变化或本地损坏时返回非 0。 - `repair` 在有异常资源时尝试重新下载并修复,成功后重新写 manifest 和 snapshot。 - `doctor` 检查输出目录、后台状态目录、curl/unzip、代理解析、后台 PID、RPC socket、资源锁和 daemon 控制锁。 - `clean-stable` 只能在后台未运行且 RPC socket 不可连接时清理 `.part`、`.tmp`、失效或损坏的 PID、socket、资源锁和 daemon 控制锁,不删除正式资源文件。 如需调整间隔: ```bash cargo run -p bat-infrastructure --bin bat -- \ --auto-discover \ --watch \ --interval 30m \ --error-retry 60s ``` 默认平台是 `Windows,Android`,无需显式传 `--platforms`;只有要覆盖默认平台时才传。`--interval` 是正常检查周期,默认 `1h`;watch/daemon 模式还会在每天北京时间(UTC+8)`03:00`、`16:00`、`18:00` 强制执行一次自动刷新,该轮会注入 `force=true`,并且会中断普通 interval 的 sleep。`--error-retry` 是下载、发现或校验失败后的重试周期,默认 `60s`,也可以用 `--error-retry-seconds 60`。CLI 默认启动时向 stderr 打印 `BlueArchiveToolkit` ASCII banner,并把阶段进度日志写到 stderr,包括自动发现、proxy、server-info、marker、catalog、audit、download、snapshot 和 publish 阶段;download 阶段会输出总体下载进度和单文件开始/完成状态,audit 阶段会输出官方 `.hash`、本地 BLAKE3、需修复项和 ZIP 结构校验结果摘要。daemon 还会写 `bat-events.jsonl` 结构化日志并按大小轮转。命令结果默认以人类可读摘要写到 stdout。需要纯机器输出时加 `--json --no-progress`,需要显式开启进度日志则用 `--progress`;只想关闭横幅但保留日志时可加 `--no-banner`。错误时 stderr 输出 JSON error,watch 模式下错误 JSON 的 `next_retry_seconds` 使用失败重试周期;如果未关闭 progress,错误 JSON 前可能已有 banner 和进度日志。普通错误 exit `1`,资源目录锁冲突 exit `75`,`verify` 或 `doctor` 发现问题也返回非 0。 生产可以直接运行 `--watch`,也可以用 `--daemon` 后台运行,或者用 systemd service、容器或 Go 进程守护它。cron/systemd timer 仍可调用单次模式,但不再是 Rust 自动更新的唯一方式。项目是否热更新、热重载或重启进程,由上层业务集成决定。生产资源目录应使用独立输出目录,不要指向现有客户端或人工维护的资源目录;上层读取资源时应读取 `--output/current`,不要读取 `.staging` 或 `versions` 中未切换的目录。非 dry-run 每轮会创建 `--output/.official-sync.lock`,防止并发写同一资源目录;live daemon 还会阻止前台写命令直接修改它正在管理的同一目录。 需要只做探测时可以加 `--dry-run`。需要关闭本地 audit 或 repair 时可以显式使用 `--no-audit-local` 或 `--no-repair`,但生产同步默认应保持开启。 ## 6. 真实全量 smoke 真实官方网络全量拉取 smoke 已固化为 runbook 和脚本: ```bash scripts/official-full-pull-smoke.sh # 或 make official-smoke ``` 默认输出在 `/tmp/bat-official-smoke-/`,脚本会执行 dry-run plan、首次全量拉取、二次 `up_to_date`、本地文件破坏后的 `repair`、repair 后 `verify`,并检查 stderr progress log 中存在总体下载进度、单文件进度和校验结果摘要。完整说明见 `docs/guides/official-full-pull-smoke.md`。 ## 7. 例外输入 可接受的 `server-info` 输入是: - `--auto-discover` - `--server-info-url <官方 URL>` - `--server-info-file <官方文件名>` - `--server-info-path <本地官方 JSON>` 如果没有显式 `server-info` 输入,必须手动加 `--auto-discover` 才会走官方 metadata / `GameMainConfig` 辅助发现链路。不要在 Linux 生产任务里依赖已安装启动器或本地客户端目录。 ## 8. 代码入口 当前可用的用户入口: - `infrastructure/examples/official_launcher_bootstrap.rs` - `infrastructure/examples/official_pull_plan.rs` - `infrastructure/src/bin/bat_official_sync.rs` - `infrastructure/examples/official_update_check.rs`(历史/开发入口;生产优先使用 `bat`) - `adapters/examples/yostar_jp_client_bootstrap.rs` - `adapters/examples/yostar_jp_discovery.rs` - `adapters/examples/yostar_jp_inventory.rs` ## 9. 验证 推荐验证命令: ```bash cargo test -p bat-adapters cargo test -p bat-infrastructure cargo test -p bat-infrastructure --example official_launcher_bootstrap -- --nocapture cargo test -p bat-infrastructure --example official_pull_plan -- --nocapture cargo test -p bat-infrastructure --bin bat -- --nocapture ```