macOS 灾后状态恢复:Keychain 重建、Syncthing 重配对、OneDrive 冲突处理
系列文章:本文是「Gemini 灾难恢复」系列的第 3 篇。
- Gemini CLI 误删 Home 目录:cd 失败 + find -delete 的事故与恢复
- Dotfiles 统一管理:11 台跨平台设备的 symlink + Git 方案
- macOS 灾后状态恢复:Keychain 重建、Syncthing 重配对、OneDrive 冲突处理(本文)
这篇文章讨论 Home 目录删除后的状态层恢复。事故本身、根因链条和受损范围已经在前一篇里写过;前提是系统已经能启动,基础软件已经重装,dotfiles 也已经重新部署,这里要处理的不是“配置怎么拉回来”,而是“系统原有状态怎么修回来”。
恢复工作主要分成三个维度:
- Keychain 登录态与本地信任关系
- Syncthing 设备证书与配对关系
- OneDrive 冲突文件与版本收敛
前一篇已经覆盖事故本身,dotfiles 那篇也已经覆盖配置恢复;这篇只记录状态层问题。
Keychain:不只是密码箱
~/Library 被删之后,Keychain 基本被清空。实际影响并不只是“少了几个密码”,而是整台 macOS 的一部分身份状态丢失了。
直接后果之一是 Apple ID 自动登出,iCloud 同步中断。系统会反复要求重新登录,一批依赖 Keychain 凭证的服务也随之失去登录状态,需要重新授权。
这里有一个恢复边界很明确:1Password 只能补回我主动保存进去的那部分密码,不能补回只存在于 Keychain 里的本地服务凭证。后者如果没有第二份副本,就只能在下次使用时重新设置。
SSH 这一层也受影响。私钥文件从备份里恢复之后,git push 仍然不能直接回到事故前的体验,因为 SSH key 的 passphrase 缓存已经丢失,每次都会重新提示输入。后面我把 SSH key 重新加回 Keychain,这部分工作流才真正恢复。
这里的判断标准不是“文件是否恢复”,而是“登录态和信任关系是否恢复”。Keychain 问题本质上是状态丢失,不是单纯的密码文件缺失。
Syncthing:11 台设备逐个重新握手
Syncthing 的问题是设备身份丢失。
我的 Tailscale 网络里有 11 台设备,平时依赖 Syncthing 在多台机器之间同步文件。事故之后,air 这台 MacBook Air 上的 Syncthing 配置和证书文件被删掉,结果不是“装回客户端就结束”,而是它在其他设备眼里变成了一个新的、未被信任的节点。
原因很简单:Syncthing 识别的是设备 ID 和证书,不是机器名。同样叫 air,只要证书变了,对其他节点来说就是另一台设备,所以别的机器上会显示成“未知设备”。
恢复过程没有捷径,只能把 11 台设备逐个重新配对。好处是大部分设备都能通过 Tailscale 远程连上,不需要逐台到场操作;但流程本身仍然是机械且耗时的:
- 在一端接受新设备
- 在另一端确认共享目录
- 观察连接是否建立
- 核实同步是否正常
真正花时间的不是点“接受”,而是确认恢复后的同步状态。重新配对之后,需要逐个目录判断:
- 哪些目录可以直接从其他设备补齐
- 哪些目录已经在事故和恢复过程中出现缺失
- 哪一端才是当前最完整、最可信的版本
Syncthing 这里恢复的不是应用本身,而是设备之间原有的配对关系和同步拓扑。
OneDrive:几百个带 (2) 的冲突文件
OneDrive 处理的是数据冲突层。
Home 目录被删之后,我一边从备份恢复,一边又有云端同步继续运行。本地恢复文件、云端旧版本、恢复过程中的中间状态在多个时间点交错,最后表现为大量带 (2) 后缀的副本文件散落在各个目录里。
这些冲突文件来源并不单一,至少包含几类情况:
- 云端旧文件重新落地,与刚恢复的本地版本撞名
- 恢复过程中的中间文件先被同步上去,后续又和更新版本并存
- 本地和云端都认为自己是最新版本,客户端只能保守地各保留一份
因此,文件名多出一个 (2) 并不只是重名问题,而是不同时间点、不同来源、不同可信度的数据混在一起。
这里我采用的处理策略很明确:先停同步,再按目录比对来源,确认哪个版本保留,需要时手动合并,最后再恢复自动同步。顺序不能反。
如果边同步边清理,客户端会继续依据尚未收敛的状态制造新的冲突,相当于一边清理一边重新污染现场。OneDrive 这一层最耗时的不是技术实现,而是判断成本:每个目录都要重新判断哪个是旧的,哪个是新的,哪个只是恢复过程中的过渡产物,哪个版本已经被其他设备依赖。
为什么这些比 dotfiles 难
dotfiles 恢复相对直接,因为配置文件是静态描述,通常有明确的 single source of truth。仓库还在,就能 git clone;symlink 关系写清楚了,就能重新部署。
Keychain、Syncthing 和 OneDrive 冲突不是同一种问题。它们都属于运行中的状态:
- Keychain 保存的是登录态和本地信任关系
- Syncthing 保存的是设备证书和配对关系
- OneDrive 冲突混着的是本地与云端尚未收敛的数据
这些内容不在 Git 仓库里,也不是“安装完再导入一份配置”就能恢复。配置可以重建,状态只能修复;前者依赖定义,后者依赖历史。
这也是为什么后半段恢复比前半段重装更耗时间。软件重装有进度条,配置恢复有脚本,状态修复则需要逐项确认哪些连接、信任和版本关系已经断掉,再一个个接回去。
事后改了什么
事故之后真正补上的不是更多重装步骤,而是状态分层备份。
现在的做法大致分成几层:
- 配置继续放 Git,这一层最容易恢复
- 密码和凭证不再只依赖系统当前的 Keychain 状态,关键内容要么在 1Password 里有副本,要么单独做 Keychain 导出
- Syncthing 的配置和证书额外备份,避免节点身份丢失后重新构建整张配对关系
- 对关键目录增加比 Time Machine 更明确的快照,避免同步盘在短时间内把错误版本快速传播
另外两个操作习惯也固定下来了。第一,删除类命令先 dry-run,这已经从“应该做”变成了硬规则。第二,OneDrive 里的重要目录尽量开启版本历史;冲突未必能完全避免,但至少需要保留一个可回看的时间点。
这次恢复说明,Home 目录事故的后半段主要是状态修复,不是软件重装。系统“能用”只代表基础环境回来了,不代表登录态、设备关系和同步状态已经恢复。以后做灾难恢复准备时,状态层备份必须和配置管理放在同等优先级。