Back to Blog

哪怕只有 1% 的概率丢数据,我也输不起:给 Obsidian 上一道“终极保险”

林小卫很行

为什么我有 Mac 和云同步,还要折腾 NAS?

作为 Obsidian 的重度用户,我的笔记原本是用 Mac 本地 + 腾讯云(Remotely Save) 做多端同步的。这套方案平时用着挺顺手,但最近听到几个“插件 Bug 导致数据全丢”的案例,让我看着这几年积累下来的心血,心里总觉得不够踏实。

um.jpg

为了给“数字大脑”上一份终极保险,我盯上了家里那台华为家庭云存储(NAS)。虽然它不像群晖或极空间那样功能花哨、操作丝滑,但作为一个物理隔离的本地硬盘,它是最可靠的“第四面墙”(Mac 本地 + 腾讯云 + NAS)。

如果哪天云同步真的出了岔子,至少回家连上 NAS,我的“大脑”还完完整整地躺在那儿。

想手动备份,却被 Finder 和 Emoji 劝退了

刚开始,我想得挺简单:既然就是为了多一份保险,那我就定期手动把 Mac 上的 Obsidian 仓库复制到 NAS 上不就行了?

结果操作了一次,我就发现不想再做第二次了。

首先是 Finder 直接复制非常慢。Obsidian 的仓库里充满了成千上万个小文件(Markdown 笔记、图片、插件配置),Finder 处理这种海量小文件时,会逐个建立连接、传输,速度慢得让人怀疑人生,像是在用镊子一粒粒地搬运沙子。

sand.jpg

其次,也是最让我头疼的,是 文件名的兼容性问题

为了让笔记标题生动一点,我的很多文件名里都直接用了 Emoji,比如 🧑🏻‍💻_我的主页.md。Mac 的文件系统对 Emoji 支持得很好,但当我把它们复制到 NAS 的 SMB 共享卷时,Finder 直接报错中断了,提示“文件名包含目标卷不支持的字符”。

我试着用终端排查了一下:

cd /Users/davidlin/Documents/Obsidian/MyVault
find . -name '_My_Homepage_md_'

发现报错的不止是我自己命名的笔记,还有很多插件生成的缓存文件(比如 .smart-env 目录下的 .ajson 文件),它们的文件名也稀奇古怪。

这就意味着,如果我要坚持“直接复制”,我就得改掉所有带 Emoji 的笔记名,还得时刻小心插件会不会生成什么怪文件。这简直是因噎废食,为了备份个数据,还得牺牲我原本舒适的使用习惯?

既然“搬运沙子”费劲,不如“集装箱”运输

既然直接复制零散文件会遇到各种“查户口”般的兼容性检查,那能不能换个思路?

如果在 Mac 本地,先把整个仓库打包成一个 Zip 压缩包,然后再把这个 Zip 包丢到 NAS 上呢?

这个逻辑就像是:我不跟你纠结每一个沙粒(文件)叫什么名字、长什么样,我直接把它们装进一个密封的集装箱(Zip 包)。NAS 只需要接收这个集装箱,它根本不需要知道里面装了什么,自然也就不会因为“里面有个文件名字带 Emoji”而拒绝接收了。

truck.jpg

除此之外,这样做还有两个显而易见的好处:

  1. 传输极快:复制一个 2GB 的大文件,比复制 20000 个 100KB 的小文件,速度要快出好几个数量级。
  2. 隔离干扰:NAS 上只存 Zip 包,不会因为里面有 .DS_Store 或者乱七八糟的缓存文件而把 NAS 的目录弄得很乱。

需要恢复的时候,把 Zip 包拉回 Mac 解压,一切又回到了熟悉的模样。

把手动变成自动化:一个 Raycast 脚本

思路通过了,但我肯定不能每次备份都手动去敲压缩命令,那样太不极客了,也很容易因为懒而坚持不下去。

正好前段时间Raycast 的脚本给我提供了帮助(参考:因为受不了“手动同步”的蠢,我让 Raycast 和 AI 接管了我的博客),我就想着,能不能把这一套动作也封装成一个 Raycast Script Command?

目标很简单:按下快捷键,脚本在后台默默完成“打包 -> 传输 -> 清理”,如果有问题就弹窗告诉我。

如果你也想试试,可以参考下面这个脚本逻辑。

核心步骤

  1. 定义路径:告诉脚本你的 Vault 在哪,NAS 挂载在哪。
  2. 前置检查:确认 NAS 已经挂载好了(不仅是插了电,还要在 Finder 里连上)。
  3. 本地打包:在 Mac 的临时目录生成 Zip,顺手排除掉 .DS_Store 和插件缓存。
  4. 搬运与清理:把 Zip 搬到 NAS,然后删掉本地的临时文件。

给非技术背景朋友的温馨提示: 不懂代码也没关系,你只需要把下面这段“咒语”复制下来,保存成一个 .sh 文件(例如 backup.sh),就可以直接用了。

这是一个示意脚本(ob-backup-vault-to-NAS.sh):

#!/bin/bash

# @raycast.schemaVersion 1
# @raycast.title Backup Obsidian to NAS
# @raycast.mode fullOutput

# 配置你的路径
VAULT_DIR="/Users/davidlin/Documents/Obsidian/MyVault"
NAS_DIR="/Volumes/MyNAS/Backups/Obsidian"
TEMP_DIR="/tmp/ob_backup"
DATE=$(date +%Y-%m-%d)
ZIP_NAME="MyVault_${DATE}.zip"

# 1. 检查 NAS 是否挂载
if [ ! -d "$NAS_DIR" ]; then
  echo "Error: NAS 未挂载,请先连接 SMB。"
  exit 1
fi

# 2. 准备临时目录
mkdir -p "$TEMP_DIR"
mkdir -p "$NAS_DIR"

# 3. 打包(排除不必要的缓存)
echo "正在打包..."
cd "$(dirname "$VAULT_DIR")"
zip -r -q "$TEMP_DIR/$ZIP_NAME" "$(basename "$VAULT_DIR")" \
    -x "*.DS_Store" \
    -x "*/.smart-env/*"

# 4. 复制到 NAS
echo "正在传输到 NAS..."
cp "$TEMP_DIR/$ZIP_NAME" "$NAS_DIR/"

# 5. 清理本地缓存
rm "$TEMP_DIR/$ZIP_NAME"

echo "✅ 备份完成:$ZIP_NAME"

把这个脚本保存到你的 Raycast 脚本目录,给个执行权限(chmod +x),就能在 Raycast 里直接搜到它了。

建立“抗脆弱”的系统,是为了更从容地创作

折腾这么一圈,可能有朋友会问:至于吗?一个笔记而已,又不是可口可乐的配方,搞得这么如临大敌。

其实,这不仅是为了防范那个“万一”的 Bug,更是为了让自己在写作和记录时,内心能有一种“有底”的安稳感。

当我们不再担心“数据会不会丢”、“同步会不会出错”这些技术琐事时,我们才能真正把注意力集中在内容本身,去捕捉那些稍纵即逝的灵感。

技术归根结底是为创作服务的。最好的技术,就是当你需要它时它坚如磐石,当你不需要它时,它几乎不存在。

现在,每当我敲完一天的字,在 Raycast 里随手敲下 Backup,看着那个绿色的 亮起,心里就会特别踏实:

好了,都存好了,明天又是崭新的一天!

这就像我在 48 小时手搓平行世界(下):AI 并不是万能的,但父爱是 里写的那样,这些折腾,终究是为了守护我们在乎的东西。

coffe.jpg