薅元宝Bot(OpenClaw)羊毛来养马(Hermes)(二):消失的爱马仕 📅 2026/7/22 3:48:42 起因Hermes飞书突然不回话了某天中午常用的飞书机器人突然没了动静。发消息过去没有任何响应。第一反应是网络问题或者服务挂了登上去一看果然Hermes Gateway 进程不在了。第一轮修复能跑就行快速处理了一下重新解压安装 hermes-agent 包装上所有依赖lark-oapi、websockets、croniter 等从备份恢复配置文件重新注册 systemd 服务启动跑起来了。飞书连接恢复WebSocket 也连上了。但事情没这么简单。很快又出状况——飞书那边发消息收到的是Hi~ I dont recognize you yet!Heres your pairing code: XXXXXXXX配对白名单丢了。重新审批一次好了。然后又报 TypeErrorset_session_vars() got an unexpected keyword argument profile —— 旧版本 gateway 包冲突。加个兜底修好了。然后又报 401 无效凭证 —— 备份没完全恢复API Key 丢了。重新加载好了。一个接一个的问题像打地鼠。这时候一个疑问浮上来为什么会一次性丢这么多东西不像是某个服务崩溃更像是……整个环境被重置了。追问到底是被删除还是本来就不在用户抛来一个问题用第一性原则查一下前几天 hermes 为什么被自动删除了。自动删除是直觉判断。但直觉可能错。先不预设结论列证据时间事件6月13日Hermes 安装在宿主机上备份磁盘里有记录6月30日磁盘快照当时宿主机完整文件系统里 Hermes 还在7月6日 21:37容器首次启动journal 里只有 openclaw-gateway没有 hermes-gateway7月9日 12:34pip 重新安装 hermes-agent7月9日 12:40hermes-gateway 第一次启动随即崩溃缺飞书配置时间线一读真相就出来了Hermes 不是被删除的——它从来就不在 Docker 镜像里。还原事发经过最初状态Hermes 装在宿主机上不是 Docker 镜像的一部分Dockerfile 里没有7月6日容器重建用 Docker 镜像重新创建了容器新容器基于干净镜像里面没有 Hermes7月6日-9日系统一直在运行OpenClaw 正常工作但 Hermes 实际上已经不存在了——只是没人发现7月9日中午Systemd 尝试启动 hermes-gateway → 立即崩溃因为 Hermes 不存在→ 发现问题 → 开始排查这解释了为什么一次性丢了这么多东西不是删了某个文件而是整个可写层被重置了。根因Docker 的分层机制为什么 OpenClaw 没事Hermes 就丢了本质区别在于安装位置不同OpenClaw → 在镜像层只读 base layerDocker 镜像构建时就打进去了存在 overlay 的只读基础层容器重启、重新部署只要还是同一个镜像层OpenClaw 就在不会丢Hermes → 在可写层upperdir用 pip install 后装进系统目录写入的是 overlay 的可写层upperdir每次重建容器upperdir 被重置Hermes 就消失了一句话一个是原厂自带一个是后装的APP——手机恢复出厂设置原厂的还在后装的全没。为什么 Docker 镜像里没有 Hermes很简单——基础镜像的 Dockerfile 里没有写公开的 OpenClaw Docker 镜像也不带。是我们手动装进去的没被固化到任何镜像层。解决方案启动钩子 持久卷备份直接改 Docker 镜像做不到——镜像托管在云上的构建系统GitHub Actions 容器仓库没有仓库的写权限。但换个思路不一定非要打进镜像。做两件事一、启动时自动检测重装在容器 entrypoint 加一个钩子脚本容器启动↓检查 hermes 命令是否存在且可用├─ 存在 → 跳过正常启动毫秒级└─ 不存在 → 自动 pip install 安装 → 启动效果容器重建后第一次启动多花 3-5 秒自动装好正常重启完全不影响速度只要 pip 能访问就一定能恢复二、配置/记忆实时备份到持久卷光装回来不够配置、记忆、技能这些数据也要保留。把这些关键目录实时备份到持久卷配置文件记忆文件技能目录对话历史容器重建后自动从持久卷恢复。备份大小约 4MB毫秒级完成。效果对比维度装进镜像启动钩子备份重建后状态完好✅✅自动恢复无需人工✅✅启动速度立即就绪首次启动多3-5秒依赖外部网络❌✅需要pip配置变更自动同步❌需重打镜像✅实时备份版本升级需重打镜像自动最新版严格说这不是完美持久化——完美持久化确实应该写进 Dockerfile。但在没有镜像仓库写权限的环境下这个方案的实际效果几乎等同于装进镜像甚至在配置同步和版本升级上还更灵活。几点启示1. 出问题时先别急着修先问为什么会这样第一轮修复只花了十几分钟但如果停在那里下次容器重建还会丢。根因不解决问题就会反复出现。2. 被删除了是直觉不是结论第一反应往往是谁删了我的东西。但用第一性原则往下挖一层——东西不见了不一定是被删了也可能是从来就不在这个环境里。区分被删除和未被包含决定了后续的修复方向完全不同。3. 持久化的本质数据放在哪一层Docker 环境里判断一个东西会不会丢不用记复杂规则就问一个问题它在镜像层只读还是在可写层upperdir镜像层的重建不丢可写层的重建就没。想持久化要么打进镜像要么挂持久卷。就这么简单。