网盘加密备份与运维(跨电脑迁移)
何时使用本 Skill
分两类意图。判定不清时按「用户说的是本地文件要去网盘,还是网盘里的东西要动」来分。
A 类:加密备份(本地 → 网盘)
用户想让本地文件/文件夹上到网盘,且目的是留存或跨机器迁移:
| 用户在说 | 实际意图 |
|---|---|
| 「备份一下」「帮我把这些文件备份了」「备份这个文件夹」 | 本地文件要上云留底 |
| 「备份到网盘」「传到百度网盘」「上传到网盘」「存网盘」「同步到网盘」 | 明确要传到网盘 |
| 「换电脑了」「换机」「跨电脑迁移」「怎么把文件弄到新电脑」 | 迁移场景,本 Skill 的核心场景 |
| 「加密后再传」「加密备份」「打个加密包」「AES 加密」 | 强调加密需求 |
| 「备份 Skill / 备份技能 / 备份到云端」 | 备份目标里含技能目录 |
B 类:网盘内运维(网盘内增删改查)
用户要操作网盘里已有的东西:
| 用户在说 | 实际意图 |
|---|---|
| 「看看网盘里有什么」「列一下网盘目录」「网盘里都有什么」 | 浏览 / 列目录 |
| 「网盘还剩多少空间」「网盘容量」 | 查配额 |
| 「把网盘理一理」「网盘太乱了」「按类型整理」「批量整理」「分类归档」 | 批量整理 |
| 「新建个文件夹」「建目录」 | 建目录 |
| 「重命名网盘里的文件」「改个名字」「移动文件」「复制到这个文件夹」 | 重命名 / 移动 / 复制 |
| 「删掉网盘里的某个文件」「删除这个文件夹」「清理网盘」「清掉旧文件」 | 删除(连接器没有的能力) |
| 「网盘里出现了百分号乱码目录」「名字是一串 %2F 的文件夹」 | 乱码目录清理(见「问题一」) |
不该用本 Skill 的情况
- 只要下载:把网盘文件弄回本地 —— 本 Skill 不做下载(见「未覆盖范围」)。
- 要分享链接:生成网盘分享/协作链接 —— 未实现。
- 本地文件互传:不涉及网盘的本地复制/移动 —— 用普通文件操作。
- 定时/增量备份:本 Skill 需用户主动发起,不做定时任务。
- 仅查询登录态:单纯想看网盘账号信息 —— 不必进完整备份流程。
本 Skill 管两件事,都在百度网盘上,共用同一套登录态与安全边界:
| 能力 | 做什么 | 在哪一节 |
|---|---|---|
| A. 加密备份 | 把本地文件/文件夹 AES-256 加密打包后传上网盘,供换电脑时取用;加密包走临时公网直链、密码走会话文本通道,用完立即下线 | 「A. 加密备份」起至「迁移说明是强制组成部分」 |
| B. 网盘内运维 | 直接对网盘增删改查:列目录、建目录、重命名、移动、复制、删除、批量整理分类归档 | 「B. 网盘内文件运维」 |
> B 是 v1.4.0 并入的:原独立技能 baidu-pan-ops 的全部能力已整合进来,
> 用来补齐网盘连接器天生的短板——连接器没有删除能力,
> 而备份流程偏偏经常要清掉旧产物(废弃版本的旧文案、%2F 乱码目录、过期加密包)。
> 两件事共用同一条 CDP 取 Cookie 链路与同一套 fail-closed 边界,
> 拆成两个技能等于让用户扫两次码、维护两份凭据说明,故合为一处。
A. 加密备份:两条通道,分工传输(v1.3.0 核心设计)
本 Skill 对加密包与密码文件使用两条完全不同的通道,
让两者在整个传输链路上从不共处:
| 对象 | 传输通道 | 是否经公网直链 | 落在哪 |
|---|---|---|---|
| 加密包(主体) | 连接器 file_upload_by_url |
是(直链只在发布窗口期有效) | 网盘备份目录 |
| 密码文件 | 连接器 file_upload_by_content(会话文本通道) |
否(不经任何公网直链) | 网盘备份目录(与加密包同处) |
威胁模型(用户明确界定):
- 要防的是「公网直链被第三方截留」 —— 直链是本方案唯一暴露在公网的环节。
所以加密包可以走直链(它本身是 AES-256 密文),而密码绝不经直链,
改走会话文本通道(file_upload_by_content,只能传文本、≤2 万字)写入网盘。 - 不考虑「网盘本身被入侵」 —— 该风险不在防护范围内。
正因为不防它,密码文件才可以与加密包放在同一个备份目录,
换电脑时一处取齐、不必两地凑。
效果:直链被截留者只能拿到加密包、拿不到密码(密码从未出现在直链上);
而合法取用者在网盘备份目录里一次拿全两样东西。
> 若日后威胁模型变化(例如要防网盘被入侵),恢复旧协议即可:
> 密码留在本地密钥目录、改走微信/短信转达,网盘目录里不放密码文件。
为什么需要这个 Skill
百度网盘没有开放「上传本地文件」的通道:
| 通道 | 限制 |
|---|---|
连接器 file_upload_by_content |
只能传文本,≤2 万字。官方明说不要传二进制 → 正好用于密码文件 |
连接器 file_upload_by_url |
需要一个公网可下载直链 → 用于加密包 |
bdpan 官方 CLI |
无原生 Windows 版(只支持 WSL);无签名可验 |
| PC 客户端 | GUI 程序,无命令行/API 入口 |
所以「把本地 zip 传上网盘」只有一条路:先给文件一个公网直链,再让网盘去拉。
本 Skill 就是用 WorkBuddy 的发布能力造这个直链,用完立刻下线。
而密码是纯文本,可以绕开直链、直接走 file_upload_by_content。
完整踩坑记录见 @references/pitfalls.md。
两个必须防住的问题
问题一:网盘里出现 %2F... 乱码文件夹
症状:网盘里多出名字长这样的一串东西 ——
%2FSkills%E5%A4%87%E4%BB%BD%2Ffile-organizer-assistant,
解出来其实是 /Skills备份/file-organizer-assistant。
原因:调用网盘接口时,dir / path 这类参数是真实路径,
其中中文和 / 由接口层去编码。但如果先把整条路径编码好、再当成字符串传进去,
服务端不会替你解码,就老老实实建了一个"名字念作 /Skills备份/..."的文件夹。
层级关系全部丢失,还会一层套一层地累积出多个乱码目录。
避免(三道防线):
- 传参前先过静态检查:
bash python scripts/check_path.py --path "<拟用的网盘路径>"
看见%xx残留即退出码 3,脚本会同时给出正确的解码结果。 - 永远传真实中文路径(如
/Skills备份/xxx),
不要手写%2F...这种编码后的整串。 - 写完后立刻列目录核对:文件名应与你期望的中文名逐字一致;
出现%就说明编码链路错了,立即停手排查。
已经产生了乱码目录怎么办:它是真实存在的普通目录,而网盘连接器没有删除能力。
本 Skill 已内置删除通道(v1.4.0 起)——走网页接口的 pan_api.py rm,
可操作全盘任意路径(含根目录),需要登录态:
python scripts/pan_api.py rm --path "/%2FSkills%E5%A4%87%E4%BB%BD%2Fxxx" --yes
--yes 是显式确认闸口,不要习惯性带上;也可以直接在网盘客户端里手动删。
问题二:任务意外中断,公网直链还挂着怎么办
风险实质:临时直链靠宿主发布能力创建,但下线只认本地目录——
平台是按「本地目录路径 → 已发布记录」的映射来找要取消的发布。
所以本地目录一旦被清掉、被移动,或换了电脑、换了会话,
可能再也找不到下线入口,链接就一直留在公网。
避免(发布台账):每次发布后立刻登记,凭记录就能恢复下线。
python scripts/publish_ledger.py add --dir "<发布目录>" --url "<直链>" --note "<备注>"
python scripts/publish_ledger.py list # 看还有哪些没下线
python scripts/publish_ledger.py list --all # 含历史记录
python scripts/publish_ledger.py done --dir "<发布目录>" # 下线后标记
python scripts/publish_ledger.py check --dir "<发布目录>" # 查风险,退出码 4 = 仍未下线
意外中断后的恢复步骤:
publish_ledger.py list找出状态仍是published的记录;- 确认那个发布目录还在(这是下线入口;被删了就按同名路径重建一个空目录);
- 对它执行
unpublish; - 用
curl验证直链返回 404; publish_ledger.py done --dir <该目录>收尾。
兜底提示:发布目录不要命名得太随意、也不要随手删——
它既是"要传的东西的来源",也是"下线入口"。建议固定用
<工作区>/.workbuddy/临时目录/<用途>-pub 这类可预期的名字。
万一目录真的丢了且无法重建,最后的办法是去发布平台的
「设置 — 数据管理 — 应用」里手工下线。
> 实践中还有一条更强的保险:发布前就把 unpublish 的命令准备好,
> 别等出了问题再找入口。
核心流程(7 步)
> 详细操作、参数与判据见 @references/flow.md。 此处只列骨架。
| 步 | 动作 | 关键工具/脚本 |
|---|---|---|
| 1 | 确认范围 + 路径校验 | check_path.py |
| 2 | 打包(AES-256)+ 密码写入密钥目录 | pack_encrypted.py |
| 3 | 准备发布目录(3 份 WAF 安全后缀副本) | prepare_publish.py |
| 4 | 发布取直链 → 验证 200 → 登记台账 | workbuddy_sites_deploy / publish_ledger.py |
| 5 | 转存加密包 + 迁移说明(走直链) | file_upload_by_url / verify_upload.py |
| 6 | 上传解密密码(走会话文本通道,不经直链) | pack_password_payload.py / file_upload_by_content |
| 7 | 立即下线 → 验证 404 → 台账 done → 三件齐套核对 | workbuddy_sites_deploy / publish_ledger.py |
三条不可颠倒的次序:
- 第 2 步打包后立刻生成迁移说明,与加密包同窗口转存(见下节);
- 第 4→5 步必须压在同一个发布窗口内做完——直链一
unpublish即全域 404; - 第 7 步先下线、再清理本地发布目录——发布目录是唯一的下线入口。
第 6 步是 v1.3.0 新增:密码文件走 file_upload_by_content 文本通道,
绝不上直链。密码明文由脚本生成 JSON 载荷,不经模型上下文复述。
同理:迁移说明也是纯文本,≤2 万字时可走同一条通道(见第 5 步的「替代通道」注),
此时一次备份里就只剩加密包需要公网直链。
迁移说明是强制组成部分
规则:每次备份,网盘目录里必须同时存在
加密包 + 迁移说明 + 解密密码三个文件(v1.3.0 起为三个)。
加密包本身不可读,说明文件是唯一告诉目标电脑"怎么解压、密码从哪来、装到哪"的东西;
少了它,备份在换机当天就是一块打不开的石头。
为什么容易被漏(本 Skill 曾踩过)
file_upload_by_url 一次只能传一个 URL,而直链又只在发布窗口期内有效。
于是「加密包」和「迁移说明」天生是两次上传——第一次只想着主包,
说明文件就很容易被当成"下一轮再说"的琐事落下。
根因是流程顺序:说明必须在打包后就生成好,并在同一个发布窗口里
与加密包一次性放齐,而不是等收尾时再补。
(解密密码走的是另一条通道,不占发布窗口,但同样属于"必传项"。)
正确做法:同一窗口放齐包与说明,密码随后走文本通道
按本 Skill "同一沙箱多次发布是合并、不是覆盖"的特性,最省事的姿势是:
- 第 2 步打包后,立刻生成迁移说明(模板见下),放进工作区输出目录;
- 第 3 步
prepare_publish.py准备发布目录后,把说明也复制进去
(说明不含密码,可直接明文放;文件名用 ASCII,避免编码问题); - 第 4 步用
.bin/.dat/.txt三种后缀同时提供加密包与说明的直链
(说明建议命名为<skill-name>_v<X.Y.Z>-迁移安装说明.dat之类的 ASCII 名); - 第 5 步把加密包与说明两个文件都转存,再一并轮询确认;
- 第 6 步用
file_upload_by_content把解密密码写入同一网盘目录; - 第 7 步一次性下线 → 验证 404 → 台账
done→ 三个文件齐套核对。
补传(历史备份缺说明或缺密码时)
若某个目录已经只有加密包、且发布已下线:
补迁移说明(优先走文本通道,不必重开直链):
说明是纯文本,≤2 万字时直接用 file_upload_by_content 补传即可
(实测 3,988 字节 .md 逐字节一致),不要为一纸说明再开一次公网窗口。
只有文档超长时才退回到下面这条直链路线:
- 单独建一个只含说明文件的发布目录(别复用旧目录,避免带走无关文件);
- 发布 →
curl验证 200 → 登记台账; file_upload_by_url传到同一个网盘目录(dir指向该_vX.Y.Z目录);- 轮询确认落地(文件名逐字匹配 + 字节数一致);
- 立即
unpublish→ 验证 404 → 台账done。
> 替换同名旧说明时:先把旧的挪出目录(连接器只能 file_move;
> v1.4.0 起也可直接用 pan_api.py rm --path <旧件> --yes 真删),再上传新件;
> 否则网盘会自动加时间戳改名,目录里就多出一份来。
> 另外注意:连接器的写操作可能"假成功",删没删掉要用 pan_api.py ls 复核(踩坑 4.6)。
补解密密码(不需直链,更简单):
直接用 file_upload_by_content 写入同一目录即可,不要为此重开直链,
更不要重新打包加密包。
> 补传不要重新打包加密包——只需补缺的文件,加密包原封不动
> (纯改名/补文件都不要重传主包,见踩坑 1.6b)。
迁移说明模板(必需字段)
# <Skill 名称> — 迁移安装说明
- Skill 名称 / 版本(取自 SKILL.md frontmatter,不臆造)
- 加密包文件名 / 大小(字节)/ SHA-256 / 加密算法(AES-256)
- 网盘位置(/Skills备份/<skill-name>_vX.Y.Z/)
- 解密密码文件名(<skill-name>_vX.Y.Z-解密密码.txt,与本说明同目录)
- ⚠️ 声明:密码文件**在网盘同一目录内**;它未经过公网直链,
仅通过网盘文本通道写入。直链截留者拿不到它。
## 一、解压 ← 必须写明 Windows 资源管理器解不了 AES 包,
用 7-Zip / WinRAR / Bandizip(macOS 用 Keka 等)
## 二、校验完整性(大小 / PowerShell 的 Get-FileHash)
## 三、安装到目标电脑(目标路径 <主目录>/.workbuddy/skills/<skill-name>/
+ 提醒目录名不可改)
## 四、版本说明(新旧版本并存,不靠改名覆盖)
## 五、安全说明(直链已下线验证 404;密码遗失则无法恢复)
禁止把密码写进迁移说明——迁移说明进的是公网直链,而密码绝不上直链。
密码要放进的是网盘上那个"解密密码.txt"独立文件(走文本通道)。
B. 网盘内文件运维(增删改查 / 批量整理)
> v1.4.0 由原 baidu-pan-ops 技能整合而来。
> 存在的理由很实际:网盘连接器没有删除能力,而备份流程经常要清旧产物
> (废弃版本的旧文案、%2F 乱码目录、过期加密包)。运维与备份共用同一套
> 登录态和安全边界,拆成两个技能反而要各配一份凭据说明。
两条路线(先选路线,再动手)
| 路线 | 脚本 | 可达范围 | 本机可用性 |
|---|---|---|---|
| 网页接口(主用) | scripts/pan_api.py + scripts/get_cookie.py |
全盘任意路径(根目录整理、/Skills备份 都能操作) |
✅ 有 Chromium 内核浏览器即可 |
| bdpan CLI(备选) | scripts/netdisk_crud.py |
严格限定 /apps/bdpan |
⚠️ 需 WSL/Linux,无原生 Windows 版 |
选路规则:目标在 /apps/bdpan 内且本机有 bdpan → 走 CLI(官方、稳定);
其余一切(含根目录、备份目录)→ 走网页接口。
首次登录(仅一次)
网页接口路线使用用户自己的登录态:
python scripts/get_cookie.py setup # 弹出专用浏览器窗口,扫码登录一次
python scripts/get_cookie.py get # 之后无头自动获取,输出 BDUSS / STOKEN
- 专用配置目录
%LOCALAPPDATA%/baidu-pan-helper/profile,与日常浏览器完全隔离; - 浏览器候选 Chrome → Edge;装在非标准路径时用环境变量
BAIDUPAN_BROWSER指定绝对路径; - 取到 Cookie 后绝不要强杀浏览器——Windows 上
terminate()等同TerminateProcess,
登录态来不及落盘,会表现为"setup说成功、紧接着get取不到"(踩坑 4.3); eval "$(get_cookie.py get)"若被本机安全策略拦下,改为在同一个 Python 进程内
用importlib加载两个脚本直接调用,凭据不经过 shell、也不落盘(踩坑 4.5)。
增删改查
# 列目录(网页接口,全盘任意路径)
python scripts/pan_api.py ls --dir /Skills备份
# 新建目录 / 重命名 / 移动(批量移动先 dry-run)
python scripts/pan_api.py mkdir --path /Skills备份/新目录
python scripts/pan_api.py rename --path /a --name b
python scripts/pan_api.py move --src /a /b --dest /分类目录 --dry-run
# 删除(必须显式 --yes):这是连接器给不了的能力
python scripts/pan_api.py rm --path "/Skills备份/旧件" --yes
# 容量 / 登录态探针
python scripts/pan_api.py quota
CLI 路线(限 /apps/bdpan,需 WSL/Linux 环境):
python scripts/netdisk_crud.py ls|names|mkdir|put|get|rename|mv|cp|rm ...
bash scripts/selftest.sh # CLI 路线端到端自测,沙箱目录自动清理
批量整理的纪律
- 先摸底、再方案、再 dry-run:列全盘 → 给出分组方案(文档 / 代码 / 电子书 /
素材 / 待人工确认…,按实际内容定)→move --dry-run出「哪个搬到哪个」的完整清单 →
用户确认后才执行; - 整目录搬移:目录很深、文件很多的同类内容直接移动整个文件夹,不逐文件操作;
- 单批 ≤ 100 项,脚本已内置批间 1.5s 节流,不要并发;
- 移动可逆(反向 move 即恢复);删除不可逆(进回收站,但批量删除前逐条确认);
- 写完必须复核:用
ls列目标路径确认落地,别信返回体(踩坑 4.6)。
运维专属坑(详见 @references/bdpan-pitfalls.md)
| 坑 | 对策 |
|---|---|
apps、百度云解压 等系统目录不可移动/改名(errno=2) |
服务端保护,不是故障,跳过它们 |
移动/删除是异步任务(async=1 返回 taskid) |
轮询 /api/taskquery 至 status=success 才算完成 |
| Cookie 库被 App-Bound 加密(Chrome 127+),解密数据库拿不到明文 | 走 CDP 读 Cookie(get_cookie.py 已实现) |
| bdpan 退出码恒 0,写操作失败也返回 0 | 解析输出 + 写入后轮询确认落地(netdisk_crud.py 已内置) |
CLI 的 ls 有四个行为坑(根目录回显自身、空目录回显自身、错误码混在 JSON 里) |
netdisk_crud.py 已逐一处理,不要绕过它直接调 bdpan |
本地路径写成 /d/...、/tmp/... 传给 Windows 原生 Python 会解析失败 |
只用 D:/... 形式;脚本里用 cygpath -m 转换(见坑位文档第三节) |
安全规则(不可违反)
- 加密包只走公网直链,密码文件绝不走公网直链(v1.3.0 核心)。
密码改走file_upload_by_content会话文本通道,直链截留者只能拿到密文。 - 加密是默认选项,用户要求明文时必须明确提示风险。
- 用完必须下线:转存成功后立即
unpublish,并验证 404。 - 发布目录保持干净:只含目标文件,绝不暴露工作区其它内容。
- 不擅自改动用户原文件:打包是读取,源文件保持不动。
- 不装未经验证的软件:不因为有"官方"二字就安装;先验证签名与来源。
- 公网暴露窗口应尽量短(分钟级),并在执行前向用户说明这一点。
- 发布必须登记台账:没有登记就没有可靠的下线入口,中断即失控。
- 网盘路径只传真实中文路径,绝不手写编码后的整串(防乱码目录)。
- 发布目录不随手删:它同时是下线入口;清理前先确认台账里已标记
done。 - 三个文件必须齐套进同一网盘目录(加密包 / 迁移说明 / 解密密码),
且加密包与说明压在同一个发布窗口内完成;密码另走文本通道补齐。
收尾前必须file_list核对三个都在。缺任一视为备份未完成。 - 密钥目录与发布目录必须分离:密码文件写入独立密钥目录
(默认~/.workbuddy/backup-keys/),绝不进发布目录——
进发布目录就意味着一并暴露到公网直链上,v1.3.0 的全部设计就白做了。
脚本层已用硬闸口拦截重叠。
(别读成"密码不进网盘":密码文件的内容仍要进网盘备份目录,
但只经规则 1 的文本通道;两条通道彼此独立。) - 密码明文不进对话与终端输出:打包脚本不打印密码;上传时由脚本生成
JSON 载荷,模型原样转发content,不在对话里复述密码。
(content仍会不可避免地经过一次模型上下文,见规则 14。) - 收尾必须告知用户"密码已随本次对话载荷传输",并提示若在意对话记录
留存可自行更换密码。这是 v1.3.0 方案唯一的残留暴露面,必须明说。 - Cookie / BDUSS 是账号级凭据(权限不止于文件,等同账号本身):
只在用户明确授权下使用;不落盘、不写日志、不进版本库、不发给任何第三方;
专用浏览器配置目录不得并入日常浏览器配置。 - 删除与批量写操作先给清单:
rm必须显式--yes,执行前把待删清单逐条给用户看;
批量移动先--dry-run。不做不可逆的猜测,宁可多问一句。 - 写操作一律复核落地:连接器的
make_dir/file_move可能"假成功"(踩坑 4.6),
所以任何写操作都用pan_api.py ls复核;判存在性用父目录列举 + 名字集合成员比对,
不要按文件名后缀猜语义。
关键坑(详见 @references/pitfalls.md)
| 坑 | 对策 |
|---|---|
WAF 拦 .zip 返回 403 |
改后缀为 .bin/.dat/.txt |
标准 zipfile 不能写 AES 加密 |
必须用 pyzipper |
| Windows 资源管理器解不了 AES zip | 迁移说明里写明用 7-Zip/WinRAR/Bandizip |
| 网盘连接器 没有删除工具 | v1.4.0 起内置:走 pan_api.py rm --path ... --yes(网页接口,全盘可达) |
| 公共图床多数被 AI 流量封禁 | 不要依赖第三方图床,用发布服务 |
| 上传后列表看不到(最终一致) | 轮询重试,别"查一次就判失败" |
| 同名文件自动加时间戳,不覆盖 | 先 file_move 挪走旧的,再上传/改名 |
file_rename 的 ondup=overwrite 改名覆盖会失败 |
先归档旧的,再改名(无冲突才成功) |
传编码后的整串路径 → 网盘长出 %2F... 乱码目录 |
先跑 check_path.py;只传真实中文路径 |
| 下线只认本地目录,目录丢/换机就失控 | 每次发布 publish_ledger.py add 登记 |
| 同一沙箱多次发布是合并,不是覆盖 | 一次发布就放齐全部文件,别指望二次发布清场 |
| 返回值"成功"≠真的写进去了 | 以"轮询后确认存在且大小一致"为唯一判据 |
路径含 .. 会跳到别的层级 |
check_path.py 规范化后比对,越界即拒绝 |
file_upload_by_content 只能传文本、≤2 万字 |
密码文件本就是纯文本,正好走这条通道;迁移说明是纯文本时同样可走,省一次直链窗口 |
| 密码文件被误放进发布目录 → 随直链暴露 | 密钥目录与发布目录分离;脚本硬闸口拦截重叠 |
| 老产物文案与新协议打架(旧密码文件写着"不要上传网盘"、旧迁移说明写着"密码不在网盘") | 脚本已改;file_list 时顺手核对文案,发现矛盾就重出(走文本通道,不必重开直链) |
系统目录不可移动/改名(apps、百度云解压) |
服务端保护,errno=2 属正常,跳过 |
| bdpan 退出码恒 0,写操作失败也返回 0 | 解析输出 + 写后轮询确认;越界路径由 netdisk_crud.py 本地 fail-closed 拒绝(退出码 2) |
网盘接口常见 errno
对返回码的正确解读能省掉大量猜测(连接器返回的 errno 同义):
| errno | 含义 | 该怎么办 |
|---|---|---|
0 |
成功 | — |
2 |
参数错误 / 路径不存在;系统目录受保护 | 检查路径写法与权限;系统目录跳过 |
12 |
文件或目录已存在 | 建目录时可视为成功;改名时说明有冲突,先归档旧的 |
-6 |
身份验证失败(登录态失效) | 重新 get_cookie.py setup 扫码 |
-8 |
目标目录下已有同名文件 | 先 file_move 挪走旧的 |
-9 |
接口限流或抖动;也可能是"目标不存在" | 可重试;若复现且目标是查询/删除对象,按"不存在"处理并复核(踩坑 4.6) |
-70 |
文件不存在 | 核对路径 |
111 |
token 失效 | 重新登录连接器 |
8001 |
删除时文件不存在 | 目标本就不在,核对清单后再决定是否重试 |
节奏与批量原则
非官方接口自动化存在账号风控的理论风险,实践上的最低风险姿势:
- 温和节奏:批量操作之间留 1–2 秒间隔,不要并发;
- 小批量:单批不超过 100 项,超了分批;
- 宁可多问一句:破坏性操作先看清单再执行,不做不可逆的猜测;
- 改动前先固定命名:目录名可预期,才不会"找不到它"(见问题二)。
网盘备份命名规范(带版本号)
网盘侧目录名、加密包名、迁移说明名、解密密码名统一带版本号,
让多版本可以并存、一眼看出是哪一版、不互相覆盖。
格式:<skill-name>_v<主>.<次>.<修订>
| 对象 | 命名 | 通道 |
|---|---|---|
| 网盘目录 | /Skills备份/<skill-name>_v<X.Y.Z>/ |
— |
| 加密包 | <skill-name>_v<X.Y.Z>-encrypted.zip |
URL 直链 |
| 迁移说明 | <skill-name>_v<X.Y.Z>-迁移安装说明.md |
URL 直链(纯文本时也可走会话文本通道) |
| 解密密码 | <skill-name>_v<X.Y.Z>-解密密码.txt |
会话文本通道 |
规则
- 版本号取自 Skill 的
SKILL.mdfrontmatter 的version:字段,不臆造;
该字段缺失时命名用_v0.0.0-unversioned,并提示用户补写version。 - 只改网盘侧与打包产物名,不改本地 Skill 目录名。
本地目录名是平台加载 Skill 的依据(.skill-list-cache.json按
filePath/slug/overrideKey定位),改名会导致 Skill 加载失败。 - 纯改名用
file_rename,不要重新上传——重传会产生时间戳副本、浪费一次发布窗口。
验证方式:改名前后fsid与字节数应完全一致。 - 升级时新版本另起
_vX.Y.Z目录(或新文件名),旧版本原地保留,
不靠改名覆盖——file_rename的ondup=overwrite对改名覆盖无效(见踩坑 1.6)。 - Windows 资源管理器解压不了 AES 包,迁移说明里必须写清解压工具。
- 解密密码文件名必须带「解密密码」字样,不得命名为
password.txt之类
易与加密包混淆的名字——它和加密包同目录,认错等于把密文当钥匙用。
依赖
加密备份(A)
- Python 隔离环境:
<用户目录>/.workbuddy/binaries/python/envs/default/
(托管 Python 的versions/目录会自动更新,装进去的包会丢,必须装进envs/default) - 必需:
pyzipper(AES 加解密)、requests - 平台能力:
workbuddy_sites_deploy(发布/下线)、百度网盘连接器
(file_upload_by_url传加密包、file_upload_by_content传密码)
环境检查:
python scripts/check_env.py
返回 ready 即可执行;缺 pyzipper 时给出安装命令后停止(加密是核心正确性,不可降级)。
网盘运维(B)
- 网页接口路线:一个 Chromium 内核浏览器(Chrome 或 Edge 均可,
用于扫码取登录态);无需额外 Python 包(只用标准库)。
非标准安装路径用环境变量BAIDUPAN_BROWSER指定绝对路径。 - bdpan CLI 路线(可选):需已安装并登录 bdpan,且只能在 WSL/Linux 下用;
可执行文件定位顺序 PATH →BDPAN_EXE→%LOCALAPPDATA%/bdpan/bdpan.exe。 - 首次使用需人工扫码一次(
get_cookie.py setup),之后全自动无头运行。
停止条件
出现以下情况立即停止,不继续写入:
- 用户说"停止""取消"
- 直链验证始终 403 且换后缀无效
- 转存后网盘字节数与本地不一致(先排查,不强行宣告成功)
- 用户拒绝加密但又要求公网传输
- 发布服务不可用(
workbuddy_sites_deploy报错) prepare_publish.py报"发布目录已存在且非空"(退出码 3)而用户尚未确认check_path.py检出路径含编码残留(退出码 3)——先改正路径再说publish_ledger.py check返回 4 但用户不愿处理遗留链接- 收尾
file_list核对时三个文件不齐(缺迁移说明或缺解密密码)——
不要宣告备份完成;按「迁移说明是强制组成部分 · 补传」流程补齐后再收尾 - 打包后未能生成迁移说明(如模板字段缺失、版本号读不到)——
先补全说明再进入发布,不要"先传包、说明以后再说" - 密码明文长度 > 20000 字符 —— 超出
file_upload_by_content上限,
不要截断(截断即密码失效),先改用本地密钥目录 + 另行走渠道的方案 - 删除操作未获用户明确确认(清单未过目、或用户没说要删)——
不要"顺手删掉";rm的--yes由用户意图驱动,不由脚本便利驱动 - 登录态失效(
errno=-6/111)——先引导用户重跑get_cookie.py setup扫码,
不要尝试绕过或复用旧凭据 - CLI 路线要求操作
/apps/bdpan之外的路径 —— 那是客户端 PathGuard 的硬边界,
改用网页接口路线,不要试图绕过
脚本实测记录
十一个脚本(10 个 Python + 1 个 shell)在隔离 Python 环境下实测:
| 脚本 | 验证内容 | 结果 |
|---|---|---|
check_env.py |
依赖探测、版本判定、状态输出 | status=ready,退出码 0 |
pack_encrypted.py |
端到端 AES-256 打包、无密码拒读、错密码拒读、生成密码文件、stdout 不含密码、密钥目录重叠拦截(退出码 3) | 8 文件打包成功,无密码读取被拒;重叠两方向均已实测拒绝。2026-10-06 改密码文件文案后回归:2 文件打包 exit 0、stdout 密码: 计数 0、重叠拦截仍为 3 |
prepare_publish.py |
三份副本生成 + sha256 一致性 + 硬闸口 | 非空目录拒绝(3)、--force-clean 放行、盘符根/主目录拒绝(2) |
check_path.py |
正常路径放行;编码残留 / .. 逃逸 / 编码混淆分别拦截 |
正常退出码 0;%2F... 与 .. 均退出码 3,结论文案按原因区分 |
verify_upload.py |
轮询确认落地、比对字节数、支持期望"不存在" | 无登录态时给出降级提示;连接器通道已实测确认字节数一致 |
publish_ledger.py |
add / list / done / check 全生命周期 | check 未下线返回 4,done 后 list 清空,记录完整可追溯 |
pack_password_payload.py |
读密码文件 → 生成 JSON 载荷;stdout 不含密码明文;超长(>20000)拦截 | 往返一致;超长退出码 3 |
get_cookie.py |
浏览器候选回退(Chrome→Edge)、CDP 优雅关闭、验活接口回退、get 轮询到 BDUSS 出现 |
本机(仅 Edge)首跑暴露 4 处缺陷并全部修复:setup 成功、get 可无头取回(详见坑位文档 4.1–4.5) |
pan_api.py |
列目录 / 建目录 / 移动 / 重命名 / 删除 / 容量;--dry-run 与 --yes 闸口 |
全盘路径实测通过;rm 对不存在目标如实返回 errno=8001,不谎报成功 |
netdisk_crud.py |
bdpan CLI 路线:ls 四坑处理、写后轮询、越界 fail-closed | ⚠️ 需 bdpan 环境,本机无原生 Windows 版,未在本机实测;越界拒绝逻辑为其自带设计 |
selftest.sh |
CLI 路线端到端自测(沙箱自动清理) | ⚠️ 同上,未在本机跑过 |
静态预检说明:skill_ops.py preflight 会因 shutil.rmtree / unlink 把 prepare_publish.py 标记为 high。这是按函数名匹配的固有判定,无法通过改写消除;其风险已由人工设计的 --force-clean 硬闸口 + 高危目录黑名单覆盖,且四种路径(正常生成、非空拒绝、force-clean 放行、高危拒绝)均已实测。
未覆盖范围
- 不做网盘 → 本地的下载:网页接口路线与连接器都没有下载能力;
bdpan CLI 路线可get,但仅限/apps/bdpan且需 WSL/Linux 环境 - 不做定时/增量备份(需要用户主动发起)
- 不代为安装 bdpan CLI 或 PC 客户端
- 不防网盘本身被入侵(用户明确界定的威胁模型)——只防公网直链被截留
- 不做网盘的分享/协作链接管理(连接器与
pan_api.py均未实现)
整合说明(前身:baidu-pan-ops)
本 Skill 的网盘运维能力(B 部分)来自原独立技能 baidu-pan-ops
(最后版本 1.0.3),于 2026-10-06 整合进来。整合理由:
- 能力互补:备份流程必须能删旧产物(废弃文案、乱码目录、过期版本),
而网盘连接器没有删除工具——这正是原备份流程反复卡住的地方; - 共用凭据:两者都用同一套登录态(BDUSS/STOKEN)与同一条 CDP 取 Cookie 链路,
拆成两个技能等于让用户扫两次码、维护两份凭据说明; - 同一套安全边界:fail-closed 越界拒绝、写入后轮询确认、批量前 dry-run,
本来就是同一套思路。
原 baidu-pan-ops 技能目录保持原样未删(不做未经确认的删除)。
它的脚本与坑位文档已在本 Skill 的 scripts/ 与 references/bdpan-pitfalls.md 中同源存在;
确认不再需要后可由用户手动移除,此后只维护本 Skill 一处。
借鉴来源(可追溯)
本 Skill 在整合前,部分防护思路曾吸收 baidu-pan-ops 的实测经验,已按本场景重写而非照搬:
| 借鉴点 | 原始出处 | 在本 Skill 的落地 |
|---|---|---|
| 「退出码 0 的假成功」 | bdpan 退出码恒 0 | 第 5 步"不信返回值" + verify_upload.py |
| 写入后轮询确认落地 | _remote_present 轮询 |
verify_upload.py,判据含字节数比对 |
| 路径规范化后再判越界 | resolve() 的 normpath 前置 |
check_path.py 的 .. 拦截 |
| 常见 errno 语义 | pan_api.py 的 ERRNO_TEXT |
本文件"网盘接口常见 errno"表 |
| 温和节奏 / 小批量 / 无并发 | 网页接口路线风控经验 | 本文件"节奏与批量原则" |
| Windows + Git Bash 路径写法 | bdpan-pitfalls.md 第三节 |
@references/pitfalls.md 4.0 |
v1.4.0 起,"借鉴"已升级为"内置":Cookie/登录态获取链路(get_cookie.py)
与 bdpan CLI 调用实现(netdisk_crud.py)随 baidu-pan-ops 一并整合进来,
不再是外部依赖。
变更记录
1.4.1(2026-10-09,版权与标识完善)
- 补齐独立许可文件:此前许可证只写在 SKILL.md 内,打包产物中没有独立的许可文件。
现随包附LICENSE.md(用.md后缀是因 SkillHub 不接收无扩展名文件)。
现随包附 CC BY-NC 4.0 官方完整法律文本(Section 1–8 齐全),文件头部另附署名块
(Copyright (c) 2026 Brandon Yang、作品名、许可标识、可以/必须/不可三句要点)。 slug与平台提交名对齐:由netdisk-encrypted-backup改为netdisk-encrypted-backup-management,
消除 CLI 入口与网页提交 slug 不一致导致的撞车风险。- 版权小节补充:尾部「作者与版权」新增
LICENSE.md文件引用,明确再分发、改编时须一并保留。 - 功能与脚本无改动。
1.4.0(2026-10-06,整合 baidu-pan-ops)
- 并入网盘运维能力:
scripts/新增pan_api.py(网页接口,全盘增删改查)、
get_cookie.py(CDP 取登录态)、netdisk_crud.py(bdpan CLI 路线)、selftest.sh;
references/新增bdpan-pitfalls.md(实测坑位与安全边界)。 - 补齐删除能力:此前"清理旧产物"只能把文件挪到子目录,现在可直接
rm。
相关表述同步改写——原「未覆盖范围 · 不做网盘文件删除」「关键坑 · 网盘 MCP 没有删除工具」
「问题一 · 走 baidu-pan-ops 删除」「与相邻 Skill 的分工」四处均已更新。 - 文档结构:正文按能力分为 A(加密备份)/ B(网盘运维),
安全规则由 14 条扩到 17 条(新增:账号级凭据、删除与批量写操作的清单闸口、写后复核落地)。 - errno 表:补
8001(删除时文件不存在),并给-9补上"也可能是目标不存在"这一实测含义。 - 原
baidu-pan-ops目录保留未动,内容与本 Skill 的 B 部分同源。
1.3.0 —— 密码改走会话文本通道(当前协议基线)
- 密码文件改走
file_upload_by_content会话文本通道,绝不走公网直链;
密码与加密包因此可以同处一个网盘目录,换机时一处取齐。 - 迁移说明补传改为优先走文本通道(实测 3,988 字节
.md逐字节一致),
不必为一纸说明重开一次公网窗口。 - 脚本层同步:
pack_encrypted.py生成的密码文件文案、--keydir说明、
收尾提示全部改为新协议措辞,消除"永远不要上传网盘""另走微信/短信"
这类与协议打架的旧文案。
作者与版权
- 作者:Brandon Yang
- 许可证:CC-BY-NC-4.0(Creative Commons Attribution-NonCommercial 4.0 International)
你可以
- 自由使用 —— 在个人、学习、研究场景下安装、运行本 Skill;
- 自由分享 —— 复制、转发、再分发本 Skill 的完整副本;
- 自由修改 —— 改编、改造、基于本 Skill 二次创作。
你必须
- 署名 —— 保留作者署名(Brandon Yang)、本许可证标识,并注明是否作了修改;
再分发时不得删除本「作者与版权」小节。
你不可以
- 商用 —— 不得将本 Skill 或其改编版本用于任何商业目的。
包括但不限于:付费销售、按次收费(含 SkillHub Pay Skill 等付费调用形态)、
打包进商业产品或服务、以本 Skill 为核心提供收费服务、
为企业客户提供有偿部署或运维。 - 附加限制 —— 不得对本 Skill 施加法律条款或技术措施,
限制他人做本许可证允许的事。
其他
- 本 Skill 按「现状」提供,不附带任何明示或暗示的担保;
使用前请自行评估风险,因使用本 Skill 造成的任何损失由使用者自行承担。 - 许可证全文见:https://creativecommons.org/licenses/by-nc/4.0/legalcode
- 随包附
LICENSE.md文件(CC BY-NC 4.0 官方完整法律文本 + 头部署名块)。再分发、改编时请一并保留本小节与该文件。 - 如需商业授权,请联系作者另行协商。