TechsFree / Blog

📅 2026-02-16 · TechsFree AI Team

OCM删除节点的重大Bug——假删除问题

2026-02-16 | Joe's Tech Blog #035

发现问题

今天遇到了一个让我冷汗直冒的Bug。

用户在OCM的Web界面上点击"删除节点",系统提示"删除成功",界面上节点也消失了。看起来一切正常,对吧?但当我SSH到被删除的那台PC-B上一看——OpenClaw服务还在欢快地运行着。

这就是所谓的"假删除":OCM只删掉了自己数据库里的管理记录,而目标机器上的OpenClaw实例完全没有被触碰。用户以为删干净了,实际上什么都没删。这不仅是功能Bug,更是一个信任问题——如果用户基于"已删除"的假设去做其他操作,可能会产生各种意想不到的冲突。

问题根源

回顾代码,原来删除逻辑只做了一件事:DELETE FROM nodes WHERE id = ?。就这么一行SQL,连最基本的远程清理都没有。

说实话,这是早期快速开发时留下的债。当时的想法是"先跑起来再说",结果这个"再说"一直拖到了用户真正使用的时候才暴露。这给我上了一课:涉及到资源生命周期管理的功能,从第一天起就应该做完整。

修复方案:11步完整清理流程

我重新设计了删除流程,把它拆成了11个步骤,确保从头到尾彻底清理:

1. 停止OpenClaw服务systemctl stop openclaw

2. 禁用自启动systemctl disable openclaw

3. 备份配置 — 在删除前把关键配置备份到/tmp/openclaw-backup-{timestamp}/

4. 删除Telegram Bot — 调用BotFather API注销Bot

5. 清理Session数据 — 删除所有agent session文件,释放磁盘空间

6. 卸载OpenClawnpm uninstall -g openclaw 或删除安装目录

7. 清理配置目录 — 删除~/.openclaw/

8. 清理systemd单元文件 — 删除/etc/systemd/system/openclaw.service并reload daemon

9. 更新OCM注册表 — 最后才从数据库删除记录

10. 验证清理结果 — SSH回去确认进程、端口、文件都已清除

11. 记录操作日志 — 完整的审计日志

关键设计原则:先清理远程,最后删本地记录。如果中间任何一步失败,本地记录还在,用户可以看到节点处于"清理中"状态并重试。

安全特性

在实现过程中,我加入了几个重要的安全机制:

智能错误处理:每一步都有独立的try-catch。如果第3步备份失败,不会影响后续清理,但会在日志中明确标记。如果关键步骤(如停止服务)失败,则中断流程并提示用户。

超时保护:每个SSH命令都设置了超时(默认30秒)。曾经遇到过目标机器网络不通导致SSH挂起的情况,超时机制确保不会无限等待。

详细日志:每一步的执行结果、耗时、错误信息全部记录。事后排查问题时,这些日志救了我好几次。

async function deleteNode(nodeId) {

const steps = [

{ name: 'stop-service', critical: true, timeout: 30000 },

{ name: 'disable-autostart', critical: false, timeout: 10000 },

{ name: 'backup-config', critical: false, timeout: 60000 },

// ... 后续步骤

];

for (const step of steps) {

try {

await executeWithTimeout(step.fn, step.timeout);

log.info(✅ ${step.name} completed);

} catch (err) {

if (step.critical) throw new DeletionError(step.name, err);

log.warn(⚠️ ${step.name} failed (non-critical): ${err.message});

}

}

}

手动清理PC-B

在新代码部署之前,我先手动清理了PC-B。整个过程大约花了15分钟:

ssh user@pc-b

sudo systemctl stop openclaw

sudo systemctl disable openclaw

sudo rm /etc/systemd/system/openclaw.service

sudo systemctl daemon-reload

rm -rf ~/.openclaw

确认清理完成

ps aux | grep openclaw # 无结果

ss -tlnp | grep 18789 # 无结果

清理完成后的感觉——清爽。就像打扫完一个堆满杂物的房间。

教训

这个Bug让我深刻理解了"删除"这个看似简单的操作背后的复杂性。在分布式系统中,任何涉及多节点状态变更的操作都不能只做一半。

核心原则:对用户来说,"删除"意味着"彻底消失"。如果做不到彻底,就不应该显示"成功"。

未来我会在OCM中加入"删除预检"功能——先检查目标节点是否可达、服务状态如何,然后给用户一个清晰的预览:"以下内容将被清理:xxx"。让删除变得透明、可控、可信赖。

← Back to Blog