ARTICLE · 1131240
小 VPS 撑不住了:我是怎么把整个 AI 助手搬到新主机的
先说清楚对象。Hermes 是一个可以自托管的 AI 助手 —— 你把它装在自己的服务器上,用 Telegram 这类聊天工具指挥它干活。它和普通脚本最大的区别是「会长」:技能、记忆、会话记录都会随时间沉淀下来。
我这台 Hermes 住在一台 2 核 CPU 、 2.4G 内存、 43G 磁盘的小 VPS 上。
半年前它还很轻。现在它长成了这样: 385 个技能文件、 4439 段会话记录、 3 个 Telegram 机器人,外加一条每天早上自动跑的信息采集管线,和一个几千篇笔记的知识库。与此同时,这台机器的磁盘占用到了 98%,负载常年在 1.7 以上。
换机器这件事,表面是运维小活,实际是道陷阱题。
重装一遍再手工填配置? 这套系统里有 400 多处写死的绝对路径,漏掉任何一处,对应功能就静默失效 —— 它不报错,只是不工作。
直接打包搬过去? 状态数据库用的是 WAL 模式(可以理解成「先记流水账、再落正式账本」),一边写一边拷贝,拿到手的很可能是一个损坏的库。
最后我把这次迁移做完了,也留下了一份 18 个坑的清单。这篇先把结论给你,再讲坑,最后说这套东西怎么复用。
一、结论:难点从来不是「搬文件」
文件同步工具谁都会用。整机迁移真正的风险,全在看不见的地方。
第一类,硬编码路径。 技能脚本、定时任务、服务定义里到处是绝对路径。这意味着新机器的家目录必须同名,否则一个复制任务就变成了几百处改写。仅仅确认这一个前提,就决定了整个方案的设计方向。
第二类,进程内存里的状态。 路由表、调度器锁、会话索引,这些东西不在磁盘上,只活在进程里。两台机器同时跑同一个机器人,会互相抢消息;同时写同一个知识库,会产生冲突。
第三类,新旧环境的差异。 时区不同,定时任务就会在错误的时刻触发;新机器镜像自带的配置,可能悄悄覆盖掉你的改动。
把这三类管住,迁移就退化成一次普通的文件同步。
二、做法:分三层,走五步
先分层。 别按文件大小分,按「重建成本」分:
再分阶段。 核心目标是把停机窗口压到最短:
| 不停机预同步 | ||
因为 P1 已经把 99% 的数据提前搬完,真正需要停机的只有最后几分钟。
两条铁律,违反任何一条都会直接坏事:
sqlite3 .backup,不能 cp。 WAL 模式下直接复制会拿到不一致的镜像。三、六个最值得说的坑
十八个坑里,这六个最有代表性。
① 清单按目录建,就一定会漏
我按助手的安装目录列了迁移清单。结果漏掉了一个放在家目录下、被 shell 启动脚本引用的密钥文件。
症状很隐蔽:每次登录都多一行「找不到文件」,而依赖这些环境变量的命令行工具会静默失去凭据 —— 不报错,就是连不上。
教训:清单要按「谁引用谁」来建,从启动脚本反向扫描,而不是正向枚举目录。
② 配置文件也讲「先到先得」
给 SSH 做加固时,我写了一个配置文件,把「只允许密钥登录」写进去。命令返回成功,看起来一切正常 —— 直到我用生效值复查,发现密码登录还开着。
原因有点反直觉: SSH 服务对同一个配置项取第一个出现的值,而配置文件是按文件名字母序加载的。服务器镜像自带的一个文件(名字以 99 开头)里写着「允许密码登录」,排在我新加的文件前面,于是我的改动被静默忽略了。
教训:把它改名成 00 开头,问题立刻解决。顺序敏感的系统里,文件名就是优先级。
③ 验证方法的假阳性
我想确认「密码登录是否已被关闭」,用一个非交互模式去连接 —— 连接失败,我一度以为加固成功了。
后来才想明白:在那个模式下,客户端本来就不会尝试输密码,所以它必然失败。这个结果和服务器允不允许密码登录毫无关系 —— 它证明的是客户端的行为,不是服务器的配置。
④ 外部可达性,不能用本机测
防火墙改完,我在本机连自己的公网 IP ,通了。听起来是个好消息。
实际上,连自己的公网 IP 会回环走本地接口,它只验证了本地放行规则 —— 外部到底能不能连进来,一点都没证明。真正靠谱的做法,是用第三方节点从外部去测。
⑤ 架构会变,脚本会过期
我给一个次要角色装独立服务时,被系统主动拒绝了。原因不是权限,而是新版程序已经改了架构:从「每个角色一个独立进程」改成「一台主机一个进程服务全部角色」。我照着旧拓扑写的脚本,在新版本上根本装不上。
教训:迁移脚本里凡是写死服务清单的地方,都要改成动态枚举 —— 写死的清单一定会漏。
⑥ 失效配置是定时炸弹
从旧机原样搬过来的配置里,有一项是「终端默认工作目录」。它指向的目录半年前就被删掉了 —— 在旧机上它其实早就失效,只是没人碰到。搬过来之后,所有新会话里的命令都以退出码 126 失败。
教训:迁移不只是搬文件,还要复核配置里的引用是否仍然有效。
四、三条能带走的原则
就算你不在做迁移,这三条也用得上。
原则一:清单按引用关系建,不按目录建。 正向枚举目录,你只能看到你想得到的东西;反向扫描引用,你才能看到系统实际依赖的东西。
原则二:凡是「可能把自己关在门外」的操作,都要有自动回滚。 改防火墙、改登录认证这类操作,先做改动前快照,再挂一个定时器:若干分钟后若没人确认,就自动还原。这次我在防火墙和 SSH 两处都用了这个模式 —— 也正是它,让这两步可以放心去做。
原则三:验证要读「生效值」,要看「第三方视角」。 「语法检查通过」是必要条件,不是充分条件;「本机能连」也不等于「外部能连」。这两处误判,这次我都亲身踩到过。
五、交付与边界
这次迁移最后沉淀出一套六个脚本的工具链:初始化 → 差异核对 → 预同步 → 停机切换 → 缺口补传 → 安全加固,再加一份 18 项复盘清单。它们都留在自建知识库的运维目录里,并且已经按这次的教训改过一轮,下次换机器可以直接复用。
适用边界:单机自建的 agent + 自建知识库。如果你需要 7×24 零中断,或者多租户隔离,这套方案不适用 —— 那些场景需要的是集群和真正的容灾,而不是一次文件同步。
最后补一个安全提醒:新机器刚上线的那段时间,通常是最脆弱的 —— 密码登录开着、没有防火墙、没有防爆破。我在加固的第一天就拦到一个正在爆破的地址(累计 175 次失败尝试)。迁移的收尾,不是「服务跑起来」,而是「服务跑起来、并且暴露面收干净」。
参考
03_ops/scripts/migration/03_ops/2026-10-05-Hermes 迁移复盘与脚本改进.md本文由 AI 辅助创作,作者进行了实测验证和编辑修改。