OpenClaw踩坑实录:私有化AI助手部署与运维的7次教训
OpenClaw 踩坑实录:私有化AI助手部署与运维的7次教训
部署自己的 AI 助手听起来很美好,真正跑起来才发现——坑比功能多。
本文记录了我在部署和运维 OpenClaw(私有化 AI 助手框架)过程中遇到的 7 个典型问题,覆盖了定时任务、Web 服务、图片处理、CSDN 发布等多个场景。每个坑都有一句话总结和解决方案,有的还画了配图,方便对照排查。
> 本文所有图片需手动上传到 CSDN,文中会标注图片位置。
先说背景
我的需求很明确:
- 在自己的阿里云服务器上跑 AI 助手
- 通过 QQ Bot 与我交互
- 自动推送国际新闻、技术内容策展
- 定期写 CSDN 博客
用的框架是 OpenClaw + QQ Bot 插件,模型接的 MiniMax。服务器是阿里云 ECS(Ubuntu),域名解析到 lsn.org.cn。
需求不复杂,但每个环节都有意想不到的坑。
坑1:定时任务执行成功,但消息没收到
现象: cron 任务明明显示"ok",QQ 却收不到消息。
排查过程:
cron 任务配置的是每日 9:05 推送国际新闻,任务确实运行了,耗时 68 秒,状态 ok。但我去 QQ 一看——什么都没有。
看日志发现 isolated session 模式下,channel: "last" 这个 delivery 模式根本不知道该往哪儿发消息。
{ "delivery": { "mode": "announce", "channel": "qqbot", "to": "qqbot:c2c:1D04898DC3290EA089D83BB0A68A385B", "accountId": "default" }}

根因: isolated session 没有"上一个 channel"这个概念,channel: "last" 找不到目标。cron 任务跑完了,但消息投递失败,状态却显示 ok——这是最迷惑的地方。
解决方案:
openclaw cron edit "<任务ID>" \ --announce \ --channel qqbot \ --to qqbot:c2c:1D04898DC3290EA089D83BB0A68A385B \ --best-effort-deliver
核心就是把 channel 从 "last" 改成具体的 "qqbot",并明确 to 地址。同样的问题影响了两个 cron:国际新闻推送和知识库自动构建,一起修复。
坑2:GitHub push 总是超时
现象: 每次 hexo generate 之后想 push 到 GitHub,总是超时失败。
根因: 服务器在阿里云,访问 github.com:443 间歇性超时,SSH 和 HTTPS 都试过,不稳定。
解决方案: 使用 HTTPS + Personal Access Token 方式。
git remote set-url origin https://ghp_token:xenial@github.com/username/repo.git
虽然不如 SSH 优雅,但稳定可靠。Token 要有 repo 权限,去 GitHub Settings → Developer settings → Personal access tokens 生成。
坑3:nginx alias 配置错了,下载链接访问 404
现象: 新闻 MD 文件存在 data/ 目录,但通过 URL 下载时总是 404。
根因: nginx 的 alias 路径配置错误。新闻文件实际在 /home/admin/.openclaw/workspace/data/,但 nginx alias 指向了 website/downloads/,两边的文件没同步。

解决方案: 修改 nginx 配置文件,让 alias 直接指向 data/ 目录:
location /downloads/ { alias /home/admin/.openclaw/workspace/data/; autoindex on;}
改完记得 nginx -s reload。
坑4:Hexo 文章目录批量生成,正则写错了
现象: 执行批量生成脚本,所有文章都生成了"Hello World"模板目录。
排查: 看一下正则提取逻辑:
# 错误写法:从文本提取标题title = re.search(r'<a[^>]*>([^<]+)</a>', text).group(1)
实际 HTML 结构是:<a title="真实标题"></a>真实标题
所以正则匹配到的是空白!
根因: HTML 结构是 标题,文本在 title 属性里,不在标签内容里。正则写反了,导致所有文章都套用了默认的"Hello World"。
解决方案:
# 正确写法:从 title 属性提取title = re.search(r'<a[^>]*title="([^"]+)"', text).group(1)
教训:写爬虫/解析器之前,一定要先看实际 HTML 结构,不要凭感觉写正则。
坑5:CSS 加载顺序导致布局被覆盖
现象: 修改了文章详情页的 CSS,刷新之后样式没变化,或者被其他样式覆盖。
根因: 多个 CSS 文件加载顺序不对,后加载的 CSS 优先级更高,把之前的样式覆盖了。具体是 enhancements.css 在 article-style.css 之后加载,但 article-content-wrapper 的 max-width 被后者覆盖。
解决方案: 在 enhancements.css 中对被覆盖的规则加 !important,或者重新调整加载顺序。更根本的解法是确认哪个 CSS 文件应该生效,避免全局样式污染。
坑6:国际新闻 cron 状态 ok 但文件没生成
现象: cron 任务状态显示 ok,但检查 data/ 目录发现新闻文件根本没生成。
排查过程:
- 看 cron 任务的
lastRunStatus: ok,lastDurationMs: 68033——跑了 68 秒 - 但
data/里没有今天的文件,最新的只到 4 月 3 日 - 9:05 触发的任务,状态 ok,耗时 68 秒,文件不存在
结论:任务跑完了,但内容生成失败了,状态却误报 ok。
根因: 任务确实执行了,但子 agent 在某个步骤失败了(比如 searxng 搜索超时),错误被吞掉没有上报。
教训: 看状态不能只看 ok,还要结合实际结果文件验证。定期检查 cron 输出是否真的生成了预期文件。
坑7:CSDN 外链图片被屏蔽
现象: 通过 API 发布文章,图片用外链 URL,CSDN 显示不出来。
排查:
CSDN 编辑器支持从 URL 插入图片,但通过 API 提交的内容里,外部图片 URL 会被过滤掉。在 PC 浏览器能看到(因为浏览器直接请求了),在 APP 或部分客户端显示破图。
尝试的方案:
| 方案 | 结果 |
|-----------------------|-----------------------------------|
| 外链 URL | ❌ 部分客户端破图 |
| base64 编码 | ❌ APP 过滤 base64 |
| CSDN 图片上传接口 | ❌ 需要实时签名,无法调用 |
| Markdown 编辑器接口 | ❌ HMAC 签名路径不同,不匹配 |
最终解决方案:
先把文章以纯文字版发布,确保文章能正常显示。然后手动去 CSDN 编辑器里,把每张图片手动上传替换。
这个方案最稳妥——只需要一次手动操作,之后就能正常显示了。
总结:踩坑心得
- isolated session 的 delivery 要显式指定 channel,不要用
last - GitHub 访问不稳定就用 HTTPS token,稳定压倒一切
- nginx 配置改完一定要 reload 并测试,不能只靠眼盯配置文件
- 正则一定要对着实际 HTML 结构写,写完要测试
- CSS 加载顺序问题用 !important 临时解决,但要记录下来彻底修
- cron 任务不仅要查状态,还要验证输出文件
- CSDN 图片问题没有完美的自动化方案,最终还是得手动来一次
> 首发于我的技术博客:https://www.lsn.org.cn
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)