Obsidian 更新灭库记:一次由程序目录放仓库引发的永久性数据丢失事故

0. 前言

今天,我因为一次看似平常的 Obsidian 自动更新,永久丢失了存放在 E:\obsidian\my_notebook 下的全部笔记数据。这不是 Obsidian 的 bug,而是我对"本地优先"软件的文件管理机制存在致命误解。

写下这篇博客,是为了用技术细节还原事故全貌,也是为了给自己立一套不可逆的备份铁律


1. 事故摘要(TL;DR)

  • 错误:将 Obsidian Vault 放在程序安装目录 E:\obsidian\my_notebook
  • 触发:Obsidian 自动更新,安装程序重建 E:\obsidian\ 目录
  • 结果my_notebook 被当作旧版本残留清理,新二进制数据(.pak/.dll)物理覆盖原扇区
  • 损失:全部 Markdown 笔记永久损坏,Hex 编辑器下无任何可读文本残留
  • 结论不可恢复,必须重建并建立工程级备份体系

2. 事故背景与环境

项目 详情
软件 Obsidian v1.x(Electron 框架构建)
操作系统 Windows 11
仓库原位置 E:\obsidian\my_notebook
数据规模 数百篇 Markdown 笔记,含科研项目(HRRP 目标识别)、文献阅读、技术笔记与日常事务
备份情况 无任何备份:无 Git、无云同步、无跨设备副本

致命错误:我将 Obsidian 的 Vault(仓库)直接放在了 Obsidian 的安装目录 E:\obsidian\ 内部,与 Obsidian.exelocalesresources 等程序文件处于同一棵树中。


3. 事故时间线(2026-05-07)

时间 事件 状态
上午 打开 Obsidian,软件提示有更新,点击确认 正常
更新后 界面变成"空白仓库",左侧文件树消失,找不到任何笔记 异常出现
10:18 resources 目录被创建(程序文件时间戳) 更新进行中
11:13 locales 目录被重建(新的语言包写入) 覆盖发生
11:31 截图发现 E:\obsidian 目录结构,确认 my_notebook 与程序文件并列 定位问题
排查中 查看 %APPDATA%\obsidian\obsidian.json,发现历史路径记录: 路径混乱
"path":"E:\\obsidian\\locales"
"path":"E:\\obsidian\\locales\\.obsidian"
说明之前曾误将程序子目录也识别为仓库
14:55 最终确认:my_notebook 内的 .md 文件已全部变为二进制残骸 数据死亡
15:03 撰写本博客,记录教训,制定重建方案 止损重建

4. 根因分析:为什么更新会吃掉用户数据?

4.1 Electron 应用的更新机制

Obsidian 基于 Electron 构建,其 Windows 端的安装目录结构如下:

E:\obsidian\
├── Obsidian.exe          ← 主程序
├── locales\             ← 语言包目录(en-US.pak, zh-CN.pak...)
├── resources\           ← 资源文件
├── *.dll                ← 系统依赖库
└── my_notebook\         ← [我的仓库,致命地放在了这里]

当执行更新时,安装程序的逻辑是:

  1. 下载新版本安装包
  2. 删除旧版本核心目录localesresources 等会被整体替换)
  3. 解压新文件到原位置

locales 是 Electron 应用的标准语言资源目录,每次更新都会被强制重建。 而我的 my_notebook 位于 E:\obsidian\ 根目录下,与程序文件处于同一棵树中。更新程序在清理旧版本残留时,将 my_notebook 视为可被覆盖的目录,直接写入新的二进制数据。

4.2 本地优先 = 你自己是唯一的备份责任人

Obsidian 的核心哲学是"本地优先、文件自由"。它允许你打开硬盘上任意文件夹作为 Vault,软件本身不对用户说"这个位置危险"。

这意味着:

  • 好处:你完全拥有数据,格式开放(Markdown),换软件也能用
  • 风险:软件不替你保管文件位置,放错地方就是你的责任

我把仓库放在程序目录,相当于把日记本夹在系统安装光盘盒里,光盘盒被换新时,日记本就被扔了。

4.3 为什么 DiskGenius 无法恢复?

数据恢复的前提是:原扇区未被新数据覆盖

但本次事故中:

  • 更新发生在 20 分钟内
  • 新版本的 .pak 语言包文件恰好写入了原 my_notebook 占用的磁盘扇区
  • 因此恢复出的不是"被删除的旧文件",而是"披着 .md 外壳的新二进制垃圾"

5. 抢救全过程与取证分析

5.1 第一阶段:定位(误以为只是路径丢失)

  1. 检查 Obsidian 的 obsidian.json,发现记录了错误路径:
    {
      "vaults": {
        "86748a667bf590e6": {"path": "C:\\Users\\sunshine\\Documents\\Obsidian Vault", "open": true},
        "fae25e6efcd4cd67": {"path": "E:\\obsidian\\locales", "ts": 1778123592942},
        "4d01587e1f352ca6": {"path": "E:\\obsidian\\locales\\.obsidian", "ts": 1778122996886}
      }
    }
    
  2. 发现 E:\obsidian\my_notebook 文件夹仍然存在,初期以为数据完好

5.2 第二阶段:发现异常(文件已非文本)

打开 my_notebook 内的 .md 文件,发现:

  • 记事本显示为乱码(``、不可读符号)
  • Notepad++ 切换 UTF-8 / GB2312 / ANSI 均无效
  • 文件大小异常(部分远大于正常 Markdown)

5.3 第三阶段:Hex 取证(确认物理覆盖)

使用十六进制编辑器(HxD)查看文件头:

Offset:  00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
0000:    68 1B 35 D9 1B C5 1C C7 8C 39 7E BA BE D6 C5 23   h.5......9~....#
0010:    8B D5 1E 3E 1A DF 69 CB AA 2E 35 9D 87 35 ED 0D   ...>..i...5..5..
0020:    1B 46 68 BC A5 24 3E 04 58 34 C6 00 78 68 7B D9   .Fh..$>.X4..xh{.

分析

  • 正常 Markdown 文件应以文本字符开头(如 # 0x23- 0x2D、或 UTF-8 汉字 E4 B8 AD
  • 该文件以 68 1B 35 D9 开头,第 2 字节即为控制字符 0x1B(ESC)
  • 整片扇区呈现高熵随机分布,无任何可识别的文本片段

结论:原始 Markdown 文本已被新版本的 .pak/.dll 二进制数据物理覆盖。这不是编码错误,不是"用 UTF-8 重新打开"就能解决的,而是文件系统层面的数据覆写

5.4 第四阶段:DiskGenius 深度扫描(徒劳)

尝试用 DiskGenius 对 E 盘进行"完整恢复 + 额外扫描已知文件类型":

  • 能扫出 .md 文件记录
  • 但恢复出的内容依然是上述二进制残骸
  • 原因:更新发生在 20 分钟内,新数据已完全占据原扇区

最终判定:数据永久丢失,无商业恢复软件可救。


6. 血的教训:三条不可违背的铁律

铁律一:程序目录 ≠ 用户数据目录

高危目录 安全目录示例
C:\Program Files\ D:\ObsidianVault\
C:\Users\name\AppData\ D:\ResearchNotes\
E:\obsidian\(安装目录) E:\MyVault\(与安装目录同级)
任何软件的 locales\resources\ 独立的、自建的文件夹

铁律二:本地优先 = 你自己是唯一的备份责任人

Obsidian 是纯本地文件管理器,不是 Notion,不是有道云笔记。它不会自动把你的笔记上传到任何云端。如果你不建立备份,单点故障 = 永久丢失

铁律三:更新/重装前,先确认仓库位置

任何 Electron 应用、任何软件的重装/更新,都可能重建安装目录。更新前必须确认:

  • 当前打开的 Vault 路径是否在安全区域?
  • 安装目录内是否残留了用户数据?

7. 重建方案:3-2-1-1-0 科研级数据保全体系

基于本次事故,我建立了以下架构,从今往后,任何单点故障都不能再导致数据丢失

7.1 架构总览

[Windows 笔记本]  D:\ObsidianVault  (工作主副本)
        │
        ├─ Syncthing ───────► [Ubuntu 服务器]  ~/ObsidianVault  (实时镜像)
        │                           │
        │                           ├─ Git 裸仓库  ~/backup/obsidian.git  (版本历史)
        │                           │
        │                           └─ 每周推送 ───► [Gitee 私有仓库]  (异地容灾)
        │
        └─ 坚果云/OneDrive 同步目录  (跨设备 + 云端快照)

7.2 各层职责与工具

层级 工具 作用 恢复场景
工作层 Obsidian + D:\ObsidianVault 日常编辑、阅读、写作 主工作区
实时镜像 Syncthing (P2P 加密直连) Win ↔ Ubuntu 实时同步 电脑硬盘损坏、系统崩溃
版本历史 Git 裸仓库 记录每次修改,可回溯任意时间点 误删、误改、被覆盖
异地容灾 Gitee/GitHub 私有仓库 服务器机房灾难时的最终兜底 火灾、盗窃、雷击
跨设备/应急 坚果云/OneDrive 手机/平板应急查看、碎片阅读 电脑不在身边

7.3 目录结构规范

D:\ObsidianVault\
├── .obsidian\                    ← 配置、主题、插件(由 Obsidian 管理)
├── 00-Inbox\                     ← 临时笔记、待整理
├── 01-Projects\
│   ├── 目标识别\             ← 按科研项目分文件夹
│   │   ├── 论文大纲.md
│   │   ├── 实验记录.md
│   │   └── 参考文献.md
│   └── 小样本\
├── 02-Papers\                     ← 文献阅读笔记
│   ├── 2026-05-综述.md
│   └── 2026-05-Domain-Adaptation.md
├── 03-Notes\                      ← 技术笔记、方法学
│   ├── Signal-Processing\
│   ├── Deep-Learning\
│   └── Tools\
├── 04-Daily\                      ← 日志、会议、待办
│   ├── 2026-05-07.md
│   └── 会议记录.md
└── 05-Archive\                    ← 已结题、已发表、不再活跃

8. 可执行配置清单

8.1 Ubuntu 服务器端(Syncthing + Git)

# 安装 Syncthing
sudo apt install syncthing

# 启动并设置开机自启
systemctl enable --now syncthing@$USER.service

# 创建同步目录
mkdir -p ~/ObsidianVault

# 创建 Git 裸仓库(版本历史)
mkdir -p ~/backup
cd ~/backup
git init --bare obsidian.git

# 每日自动归档脚本(保存为 ~/backup/auto-archive.sh)
cat > ~/backup/auto-archive.sh << 'EOF'
#!/bin/bash
cd ~/ObsidianVault
git add .
DATE=$(date +"%Y-%m-%d %H:%M")
git commit -m "auto: $DATE" --quiet
git push ~/backup/obsidian.git main --quiet
EOF
chmod +x ~/backup/auto-archive.sh

# 添加到 crontab(每天 0点、12点、18点 各归档一次)
(crontab -l 2>/dev/null; echo "0 0,12,18 * * * ~/backup/auto-archive.sh") | crontab -

# 每周推送到 Gitee(异地容灾)
(crontab -l 2>/dev/null; echo "0 3 * * 1 cd ~/backup/obsidian.git && git push gitee main") | crontab -

8.2 Windows 端(Obsidian + Git + 定时任务)

D:\ObsidianVault 目录下,打开 PowerShell:

# 初始化 Git
git init
git add .
git commit -m "init: 重建 Obsidian 仓库 - 2026-05-07"

# 连接 Ubuntu 裸仓库
git remote add server ssh://你的用户名@服务器IP/~/backup/obsidian.git
git push -u server main

自动提交脚本(保存为 D:\ObsidianVault\auto-commit.ps1):

cd D:\ObsidianVault
git add .
$date = Get-Date -Format "yyyy-MM-dd HH:mm"
git commit -m "win-backup: $date" --quiet
git push server main --quiet

添加到 Windows 任务计划程序

  1. Win + Rtaskschd.msc
  2. 创建基本任务:
    • 名称:Obsidian Auto Backup
    • 触发器:每天,每 8 小时重复一次
    • 操作:启动程序 powershell.exe
    • 参数:-ExecutionPolicy Bypass -File "D:\ObsidianVault\auto-commit.ps1"

8.3 Syncthing 关键配置

忽略模式(避免同步缓存垃圾):

.obsidian/workspace.json
.obsidian/graph.json
.obsidian/cache/
.trash/
*.tmp

版本控制:启用"简易版本控制",保留 30 个版本,防止误删。


9. 灾难恢复速查表

故障场景 恢复步骤 预计耗时
Windows 硬盘损坏 新电脑安装 Syncthing + Obsidian,从 Ubuntu 同步回 D:\ObsidianVault 10 分钟
误删单篇笔记 在 Ubuntu ~/ObsidianVault 里找回,或用 Git git checkout HEAD -- 文件名 2 分钟
误改内容想回溯 git log 找到历史版本 → git checkout <commit-id> -- 文件名 5 分钟
Ubuntu 服务器宕机 从 Gitee 克隆仓库到新服务器,重新配置 Syncthing 30 分钟
Obsidian 更新又出幺蛾子 直接卸载重装,打开 D:\ObsidianVault,数据完全不受影响 5 分钟
全部本地副本丢失 从 Ubuntu 实时镜像复制回来,或用 Git 裸仓库还原 15 分钟

10. 结语

这次事故没有技术奇迹,没有"最后一刻找回数据"的反转。我的笔记已经变成磁盘上一段无意义的二进制噪声,这是我自己造成的。

但这件事给我上了一课:在科研工作中,数据管理是一项与实验设计、论文写作同等重要的基础工程。 我们不能假设软件会保护我们,不能假设"这次不会出问题"。

从今天开始,D:\ObsidianVault 是我的唯一工作目录,Syncthing 是我的实时镜像,Git 是我的时间机器,Gitee 是我的异地保险箱。

希望读到这篇博客的人,不要重蹈我的覆辙。


附录 A:Hex 残骸样本(作为警示)

如果你也遇到了类似的 68 1B 35 D9... 型乱码,请立即停止数据恢复幻想,转向备份重建。这种高熵二进制分布意味着原始文本已被物理覆盖,不可恢复

68 1B 35 D9 1B C5 1C C7 8C 39 7E BA BE D6 C5 23  h.5......9~....#
8B D5 1E 3E 1A DF 69 CB AA 2E 35 9D 87 35 ED 0D  ...>..i...5..5..
1B 46 68 BC A5 24 3E 04 58 34 C6 00 78 68 7B D9  .Fh..$>.X4..xh{.

附录 B:每周检查清单(周五下班前 5 分钟)


posted @ 2026-05-07 15:15  sunshine5418866  阅读(189)  评论(0)    收藏  举报