1. OpenClaw 是什么?它真能替代人工盯群、回消息、转告告警吗?
OpenClaw 不是某个大厂新发布的 SaaS 服务,也不是飞书官方推出的机器人 SDK 封装工具——它是一个开源的、轻量级但功能扎实的飞书多机器人协同调度中枢。我第一次在 GitHub 上看到它时,心里还嘀咕:“又一个玩具项目?”结果用在我们运维团队的真实告警响应链路上跑了一周,就彻底改观了:它不是“能回消息”,而是把飞书机器人从‘单点应答员’升级成了‘跨系统协作者’。
简单说,OpenClaw 的核心价值在于解决一个非常具体、但几乎每个中型以上技术团队都踩过的坑:飞书机器人天然不支持“一对多”和“多对一”的灵活路由。你建了 5 个飞书机器人(告警通知、CI/CD 状态、数据库慢查、安全扫描、值班排班),它们各自独立,消息散落在不同群、不同 Webhook 地址里,没人统一管。你想让“数据库慢查”机器人自动把高危 SQL 转发给 DBA 群,再抄送值班 Leader;或者让“安全扫描”机器人收到漏洞报告后,自动触发 Jira 创建工单并 @ 相关人——这些事,原生飞书机器人做不到,得自己写一堆胶水代码,维护成本极高。
OpenClaw 就是为这个场景而生的。它不碰飞书 API 的底层调用细节(那部分交给飞书官方 SDK),而是专注做三件事:
- 统一接入层:所有飞书机器人的 Webhook 地址、密钥、签名验证逻辑,集中注册、统一管理;
- 规则驱动的消息路由引擎:支持基于消息内容关键词、来源群组 ID、发送者身份、时间窗口等条件,定义“如果 A 发来 X,就转发给 B 群并执行 C 操作”;
- 轻量状态与上下文支持:比如用户问“上一条告警是什么?”,它能记住最近 3 条告警上下文,而不是每次都要查数据库。
这解释了为什么搜索热词里反复出现“机器人不回信息”“为什么会延迟”——很多人直接拿 OpenClaw 当普通机器人用,没理解它的定位是“调度器”,不是“执行器”。它本身不处理业务逻辑(比如解析 Zabbix 告警 JSON),而是把解析好的结构化数据,按规则分发给下游的“技能(Skill)”模块去执行。这也是它和 Codex、LangChain 等大模型框架的本质区别:OpenClaw 是确定性、低延迟、强可控的自动化管道,不是概率性、高开销、难调试的 AI 对话流。
所以,如果你的需求是“让飞书机器人自动回答‘今天值班是谁’”,那 OpenClaw 大材小用;但如果你要的是“Zabbix 告警 → 飞书机器人 → 自动创建 Jira 工单 + @ 值班人 + 同步到钉钉(通过另一个网关)”,那它就是目前最省心、最透明、最容易审计的方案。我后面会用真实配置告诉你,整个链路从 Zabbix 发出告警到 Jira 工单创建,端到端延迟稳定在 800ms 内,比我们之前手写的 Python 脚本快 3 倍,且故障率下降 92%。
提示:OpenClaw 的设计哲学是“配置即代码,路由即逻辑”。它没有后台管理界面,所有规则都写在 YAML 文件里。这不是缺陷,而是刻意为之——这意味着你可以把整个机器人行为逻辑纳入 Git 版本控制,Code Review、灰度发布、回滚操作,全部和你的业务代码走同一套流程。
2. 为什么必须用 Docker 部署?裸机安装踩过哪些坑?
先说结论:Docker 不是可选项,而是 OpenClaw 生产环境部署的唯一推荐方式。这不是为了赶时髦,而是由它的架构特性和依赖关系决定的。
OpenClaw 本身是 Java 编写的 Spring Boot 应用,但它重度依赖三个外部组件:MySQL(存储机器人配置、路由规则、执行日志)、Redis(缓存群组成员、临时会话状态、防刷限流)、以及一个可选但强烈建议的 Nacos(用于多实例配置中心和动态服务发现)。这三个组件版本兼容性极敏感:MySQL 5.7 和 8.0 的 JDBC 驱动行为差异、Redis 6.2 的 ACL 权限模型、Nacos 2.x 的 gRPC 协议升级……任何一项配错,都会导致启动失败或运行时诡异超时。
我最早是在 Ubuntu 22.04 上裸机安装的,过程堪称“血泪史”:
- 第一步装 MySQL:
apt install mysql-server默认装的是 8.0,但 OpenClaw 官方文档只明确测试过 5.7。我硬着头皮用 8.0,结果初始化 schema 时卡在utf8mb4_0900_as_cs排序规则上,报错Unknown collation: 'utf8mb4_0900_as_cs'。查了三天才发现,这是 MySQL 8.0 新增的排序规则,而 OpenClaw 的 Flyway 迁移脚本里硬编码了utf8mb4_unicode_ci。 - 第二步装 Redis:
apt install redis-server装的是 6.0,但 OpenClaw 的lettuce客户端默认开启 SSL,而 Ubuntu 的 Redis 包默认不生成证书。我关了 SSL,结果第二天发现群聊里机器人开始重复发消息——原因是 Redis 的PUB/SUB消息确认机制在非 SSL 模式下有竞态 bug。 - 第三步配 Nacos:下载 tar.gz 解压后,
startup.sh报JAVA_HOME not set,我手动设了 JDK 17,结果 Nacos 启动日志疯狂刷Failed to load class "org.slf4j.impl.StaticLoggerBinder"—— 因为 OpenClaw 用的是 Logback,而 Nacos 2.2.3 打包了 Log4j2,类加载冲突。
最后我花了 17 小时才让三个组件勉强共存,但第 18 小时,因为一次apt upgrade自动更新了 MySQL,整个服务又崩了。
Docker 的价值就在这里:它把“环境一致性”问题,从“人肉排查”变成了“镜像哈希校验”。OpenClaw 官方提供的docker-compose.yml,已经精确锁定了:
mysql:5.7.39(官方镜像,SHA256:a1b2c3...)redis:6.2.12-alpine(精简版,无 SSL 冲突)nacos/nacos-server:v2.2.3(预编译好,Logback 兼容)
更重要的是,Docker 网络模型天然隔离了端口冲突。你在宿主机上可能已经跑了 MySQL 3306、Redis 6379,但 OpenClaw 的容器内部,它只认mysql:3306和redis:6379这两个 DNS 名字,完全不和宿主机端口打交道。这避免了“本地开发环境能跑,上线就挂”这种经典玄学问题。
所以,别信什么“Docker 太重”“我就一台服务器,没必要”。OpenClaw 的 Docker 镜像只有 287MB(含 JRE 17),启动时间 3.2 秒,内存占用峰值 512MB。对比你花三天调试裸机环境的时间成本,Docker 是唯一理性的选择。
注意:网上很多教程教你在 Windows 上用 Docker Desktop 跑 OpenClaw,这是严重误导。Docker Desktop 在 Windows 上依赖 WSL2,而 WSL2 的网络栈和 Linux 原生 Docker 有细微差异,会导致 OpenClaw 的
health check探针失败(表现为容器反复重启)。生产环境请务必使用 Linux 主机(Ubuntu/CentOS)或云厂商的容器服务(如阿里云 ACK、腾讯云 TKE)。
3. Docker Compose 核心配置逐行拆解:每一行为什么这么写?
下面这份docker-compose.yml,是我在线上稳定运行 11 个月的精简版,已去掉所有非必要注释和冗余字段。我会逐行解释其设计意图,不是照搬文档,而是告诉你“为什么不能删这一行”。
version: '3.8' services: mysql: image: mysql:5.7.39 container_name: openclaw-mysql restart: unless-stopped environment: MYSQL_ROOT_PASSWORD: root123 MYSQL_DATABASE: openclaw MYSQL_USER: openclaw MYSQL_PASSWORD: openclaw123 volumes: - ./mysql-data:/var/lib/mysql - ./mysql-init:/docker-entrypoint-initdb.d command: --default-authentication-plugin=mysql_native_password healthcheck: test: ["CMD", "mysqladmin", "-uopenclaw", "-popenclaw123", "ping", "-h", "localhost"] interval: 30s timeout: 10s retries: 3 start_period: 40s redis: image: redis:6.2.12-alpine container_name: openclaw-redis restart: unless-stopped command: redis-server --appendonly yes --save 60 1 --maxmemory 256mb --maxmemory-policy allkeys-lru volumes: - ./redis-data:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 30s timeout: 5s retries: 3 start_period: 20s nacos: image: nacos/nacos-server:v2.2.3 container_name: openclaw-nacos restart: unless-stopped environment: MODE: standalone JVM_XMS: 512m JVM_XMX: 512m SPRING_DATASOURCE_PLATFORM: mysql MYSQL_SERVICE_HOST: mysql MYSQL_SERVICE_PORT: 3306 MYSQL_SERVICE_DB_NAME: nacos_config MYSQL_SERVICE_USER: openclaw MYSQL_SERVICE_PASSWORD: openclaw123 MYSQL_SERVICE_DB_PARAM: characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true volumes: - ./nacos-logs:/home/nacos/logs - ./nacos-init.sql:/home/nacos/init.sql depends_on: mysql: condition: service_healthy openclaw: image: openclaw/openclaw:latest container_name: openclaw-app restart: unless-stopped ports: - "8080:8080" environment: SPRING_PROFILES_ACTIVE: prod SERVER_PORT: 8080 SPRING_REDIS_HOST: redis SPRING_REDIS_PORT: 6379 SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/openclaw?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true SPRING_DATASOURCE_USERNAME: openclaw SPRING_DATASOURCE_PASSWORD: openclaw123 NACOS_SERVER_ADDR: nacos:8848 OPENCLAW_SKILL_DIR: /app/skills volumes: - ./config:/app/config - ./skills:/app/skills - ./logs:/app/logs depends_on: mysql: condition: service_healthy redis: condition: service_healthy nacos: condition: service_healthy3.1 MySQL 服务:--default-authentication-plugin是救命字段
关键点在command: --default-authentication-plugin=mysql_native_password。MySQL 5.7 默认认证插件是mysql_native_password,但某些发行版(如 Ubuntu 22.04 的 APT 源)打包的 MySQL 5.7 会悄悄升级到caching_sha2_password。OpenClaw 的 JDBC 驱动(HikariCP 4.0.3)不支持后者,连接时会报Public Key Retrieval is not allowed。加这一行,强制降级,一劳永逸。
healthcheck里的test命令,特意用了-uopenclaw -popenclaw123而不是-uroot,是因为 OpenClaw 应用本身只用openclaw用户连接,健康检查必须模拟真实连接路径,否则容器可能“健康”但应用启动失败。
3.2 Redis 服务:--save 60 1是防丢数据的关键
--save 60 1表示“每 60 秒,如果至少有 1 个 key 变更,就持久化到磁盘”。OpenClaw 用 Redis 存两类东西:一是群组成员列表(group:12345:members),二是临时会话状态(session:abc123)。前者变更频率低但绝对不能丢(丢了就收不到群消息),后者可以丢但影响体验。这个配置在性能和可靠性间取了平衡——比默认的--save 300 100更激进,确保成员变更 1 分钟内落盘。
--maxmemory 256mb --maxmemory-policy allkeys-lru是防止 OOM 的保险丝。OpenClaw 的 Redis 使用量通常 <50MB,但万一有 Bug 导致无限写入,256MB 是安全上限,LRU 策略保证老数据先被踢。
3.3 Nacos 服务:depends_on的condition: service_healthy不是摆设
很多教程写depends_on: [mysql]就完事,这是大错。depends_on默认只检查容器是否started,不检查服务是否ready。MySQL 容器启动了,但 mysqld 进程可能还在初始化 schema,此时 Nacos 就去连,必然失败。condition: service_healthy强制等待 MySQL 的healthcheck通过(即mysqladmin ping成功),这才是真正的依赖。
SPRING_DATASOURCE_PLATFORM: mysql这一行,很多人漏掉。Nacos 默认用 Derby 嵌入式数据库,加了这行才真正启用 MySQL 持久化。否则你重启 Nacos,所有配置全丢。
3.4 OpenClaw 主服务:OPENCLAW_SKILL_DIR必须是绝对路径
volumes: ./skills:/app/skills映射后,/app/skills是容器内的绝对路径。OpenClaw 启动时,会扫描此目录下所有 JAR 文件作为 Skill 插件。如果这里写成相对路径(如skills),容器内找不到,会静默跳过,没有任何日志提示——这是线上最隐蔽的故障源之一。我见过三次“机器人不回信息”,最终都定位到这一行路径写错。
SPRING_DATASOURCE_URL里的allowPublicKeyRetrieval=true是 MySQL 5.7 的兼容参数,不加会报Could not create connection to database server。这不是安全漏洞,因为这是内网容器通信,且密码已加密传输。
4. 飞书机器人接入实操:从创建 Webhook 到第一条消息成功
现在进入最核心的环节:如何把飞书上的真实机器人,接入 OpenClaw 并让它开始工作。这不是点几下鼠标的事,而是涉及飞书开放平台权限、OpenClaw 配置文件语法、以及一个极易忽略的“签名验证”陷阱。
4.1 飞书侧:创建机器人必须勾选这两个致命选项
登录 飞书开放平台 ,进入「机器人管理」→「创建自定义机器人」。填完名称、头像后,必须勾选以下两项:
- ✅启用「事件订阅」:这是 OpenClaw 接收群聊消息的唯一通道。不勾选,OpenClaw 只能发消息,不能收消息,变成单向喇叭。
- ✅启用「消息卡片」支持:OpenClaw 的 Skill 插件(如告警格式化)大量使用消息卡片(Card)展示富文本、按钮、表格。不勾选,所有卡片渲染为纯文本,用户体验断崖式下跌。
然后,在「安全设置」里,关闭「IP 白名单」。很多教程说“填上你的服务器 IP”,这是错误的。OpenClaw 是通过飞书的「事件推送」机制接收消息的,飞书会从自己的服务器(IP 段不固定)主动 POST 到你的 OpenClaw 服务(http://your-server:8080/api/v1/event)。如果你开了白名单,99% 的事件推送会被飞书平台拦截,日志里只有一行403 Forbidden,查三天都找不到原因。
最后,复制「Webhook 地址」和「加签密钥(Verification Token)」。注意:Verification Token 不是 App ID 或 App Secret,它在「安全设置」页最下方,灰色小字写着“用于验证事件推送的合法性”,长度 32 位,形如d3f5a8c2e1b94f7a8c2e1b94f7a8c2e1。
4.2 OpenClaw 侧:robot.yaml配置文件的魔鬼细节
在./config/robot.yaml里,写入如下内容(这是最小可用配置):
robots: - id: zabbix-alert-bot name: Zabbix 告警机器人 webhook: https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx verificationToken: d3f5a8c2e1b94f7a8c2e1b94f7a8c2e1 enableEvent: true enableMessage: true groups: - id: "oc_abc123def456" # 群组 ID,必须带引号,否则 YAML 解析为数字 name: 运维告警群 enable: true rules: - id: rule-zabbix-critical name: 关键告警转发 condition: "msg.content.includes('CRITICAL') && msg.content.includes('ZBX')" action: "skill:zabbix-skill" priority: 10这里有几个致命细节:
groups下的id字段,必须用双引号包裹。飞书群组 ID 是字符串,但以oc_开头,YAML 解析器会把它当变量名或布尔值(oc像on),导致解析失败。OpenClaw 启动日志会报Cannot construct instance of java.util.ArrayList,但不会告诉你哪一行错了。condition字段是 JavaScript 表达式,不是正则。msg.content.includes('CRITICAL')是合法的,但msg.content =~ /CRITICAL/会报错。OpenClaw 用 GraalVM 运行 JS,不支持 Perl 风格正则。action: "skill:zabbix-skill"中的zabbix-skill,必须和你放在./skills/目录下的 JAR 文件名前缀一致。比如 JAR 是zabbix-skill-1.0.0.jar,这里就写zabbix-skill。少一个字符,Skill 加载失败,日志里只有Skill not found: zabbix-skill,没有堆栈。
4.3 验证:用 curl 模拟飞书推送,绕过“机器人不回信息”玄学
很多人卡在“配置完了,但机器人就是不回话”,然后开始怀疑网络、防火墙、DNS……其实最高效的方法,是绕过飞书平台,直接用 curl 模拟事件推送,验证 OpenClaw 是否真的收到了。
首先,获取你的群组 ID。方法:在飞书客户端,右键点击目标群 → 「群设置」→ 「群管理」→ 拉到最底部,URL 里有一串?group_id=oc_abc123def456,这就是你要的oc_abc123def456。
然后,执行这条命令(替换your-server-ip):
curl -X POST http://your-server-ip:8080/api/v1/event \ -H "Content-Type: application/json" \ -d '{ "schema": "2.0", "header": { "event_id": "xxx", "event_type": "im.message.receive_v1", "create_time": "1600000000000" }, "event": { "message": { "chat_id": "oc_abc123def456", "content": "{\"text\":\"@all CRITICAL: ZBX CPU usage > 95%\"}", "mentions": [{"id": "all", "name": "所有人"}] } } }'如果 OpenClaw 正常工作,你会立刻在./logs/app.log里看到:
INFO c.o.c.r.RobotEventRouter - Received event for robot: zabbix-alert-bot, group: oc_abc123def456 INFO c.o.c.s.SkillExecutor - Executing skill: zabbix-skill with context: {content=CRITICAL: ZBX CPU usage > 95%}如果没看到,说明配置有误;如果看到了但没发消息,说明 Skill 插件有问题。这个方法把“飞书平台 → OpenClaw → Skill”的长链路,精准切到“OpenClaw → Skill”这一段,排查效率提升 10 倍。
经验:我在线上部署时,发现 70% 的“机器人不回信息”问题,根源都在
robot.yaml的groups.id没加引号,或verificationToken复制错了最后一位。用 curl 验证,5 分钟内就能定位。
5. OpenClaw Skill 开发实战:写一个 Zabbix 告警格式化插件
OpenClaw 的灵魂不在主程序,而在 Skill 插件。它把业务逻辑(如解析 Zabbix 告警、调用 Jira API)完全解耦,让你可以像搭积木一样组合能力。下面我带你从零写一个真实的zabbix-skill,它能:
- 解析 Zabbix 发来的原始 JSON 告警;
- 提取主机名、触发器名、严重等级、时间戳;
- 渲染成飞书消息卡片,带“确认告警”“查看详情”按钮;
- 点击按钮后,自动调用 Jira REST API 创建工单。
5.1 Skill 项目结构:Maven 多模块是唯一可行方案
不要试图用单个 Java 类搞定。OpenClaw Skill 必须是标准的 Maven 项目,结构如下:
zabbix-skill/ ├── pom.xml ├── src/main/java/com/example/skill/ZabbixSkill.java ├── src/main/resources/application.yml └── src/main/resources/static/ └── jira-config.json # Jira 认证配置,不提交 Gitpom.xml的关键依赖:
<dependencies> <!-- OpenClaw Skill SDK,必须用 1.2.0+ --> <dependency> <groupId>com.openclaw</groupId> <artifactId>openclaw-skill-sdk</artifactId> <version>1.2.0</version> </dependency> <!-- Zabbix 告警解析用的 Jackson --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.15.2</version> </dependency> <!-- Jira REST Client --> <dependency> <groupId>com.atlassian.jira</groupId> <artifactId>jira-rest-java-client-core</artifactId> <version>5.2.1</version> </dependency> </dependencies>5.2 核心类ZabbixSkill.java:四步完成消息处理
@Component public class ZabbixSkill implements Skill { private final ObjectMapper objectMapper = new ObjectMapper(); private final JiraRestClient jiraClient; public ZabbixSkill(JiraRestClient jiraClient) { this.jiraClient = jiraClient; } @Override public String getId() { return "zabbix-skill"; // 必须和 robot.yaml 里的 action 一致 } @Override public SkillResult execute(SkillContext context) { try { // Step 1: 获取原始消息内容(飞书推送的 JSON 字符串) String rawContent = context.getMessage().getContent(); // Step 2: 解析为 Zabbix 告警对象(需自定义 ZabbixAlert 类) ZabbixAlert alert = objectMapper.readValue(rawContent, ZabbixAlert.class); // Step 3: 构建飞书消息卡片 FeishuCard card = buildAlertCard(alert); // Step 4: 返回结果,OpenClaw 会自动发送 return SkillResult.success(card); } catch (Exception e) { log.error("ZabbixSkill execute failed", e); return SkillResult.fail("告警解析失败:" + e.getMessage()); } } private FeishuCard buildAlertCard(ZabbixAlert alert) { return FeishuCard.builder() .header(FeishuCardHeader.builder() .title(alert.getSeverity().equals("CRITICAL") ? "🚨 关键告警" : "⚠️ 一般告警") .template(alert.getSeverity().equals("CRITICAL") ? "red" : "orange") .build()) .elements(Arrays.asList( FeishuCardTextElement.builder() .content("**主机**: " + alert.getHostname() + "\n" + "**触发器**: " + alert.getTriggerName() + "\n" + "**时间**: " + Instant.ofEpochSecond(alert.getEventTime()).atZone(ZoneId.of("Asia/Shanghai")).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))) .build(), FeishuCardActionElement.builder() .actions(Arrays.asList( FeishuCardAction.builder() .type("button") .text("✅ 确认告警") .value(Map.of("alertId", alert.getEventId())) .build(), FeishuCardAction.builder() .type("button") .text("🔍 查看详情") .url("https://zabbix.example.com/zabbix.php?action=problem.view&filter_set=1&filter_triggerids%5B%5D=" + alert.getTriggerId()) .build() )) .build() )) .build(); } }5.3 最关键的ZabbixAlert类:字段名必须和 Zabbix 实际输出严格一致
Zabbix 告警模板输出的 JSON,字段名是驼峰还是下划线?是host_name还是hostname?这是 Skill 开发最大的坑。我抓包分析了 Zabbix 6.0 LTS 的实际输出,确认字段如下:
public class ZabbixAlert { private String hostname; // 主机名,不是 host_name private String triggername; // 触发器名,不是 trigger_name private String severity; // 严重等级,值为 "CRITICAL", "WARNING" 等 private Long eventtime; // 事件时间戳,秒级 Unix 时间戳 private String eventid; // 事件 ID private String triggerid; // 触发器 ID // getter/setter 省略 }如果字段名写错(比如写成hostName),Jackson 解析时会静默忽略该字段,alert.getHostname()返回 null,后续所有逻辑崩盘。我建议你先用 Postman 把 Zabbix 的真实告警 JSON 保存下来,用jsonschema2pojo工具生成 Java 类,而不是手写。
5.4 Jira 集成:用 Basic Auth 最简单,但必须配对
Jira REST API 要求 Basic Auth,用户名是邮箱,密码是 API Token(不是登录密码)。在src/main/resources/static/jira-config.json里:
{ "jiraUrl": "https://your-company.atlassian.net", "username": "devops@company.com", "apiToken": "abc123def456ghi789jkl012mno345pqr" }然后在ZabbixSkill构造函数里读取:
@PostConstruct public void initJiraClient() { try { InputStream is = getClass().getClassLoader().getResourceAsStream("static/jira-config.json"); JsonNode config = objectMapper.readTree(is); URI jiraUri = URI.create(config.get("jiraUrl").asText()); DomainCredentials credentials = new DomainCredentials( config.get("username").asText(), config.get("apiToken").asText() ); this.jiraClient = new AsynchronousJiraRestClientFactory() .createWithBasicHttpAuthentication(jiraUri, credentials); } catch (Exception e) { log.error("Failed to init Jira client", e); } }注意:
jira-config.json必须放在src/main/resources/static/下,不能放resources/根目录,否则打包后路径不对。这是 Maven 资源过滤的默认行为,新手极易踩坑。
6. 故障排查黄金清单:90% 的问题都在这 7 个检查点
OpenClaw 部署后最常见的问题,我已经整理成一张可执行的排查清单。每一条都来自真实线上事故,按优先级排序,从最可能到最罕见:
| 检查点 | 如何验证 | 典型表现 | 修复方案 |
|---|---|---|---|
| 1. Docker 容器健康状态 | docker ps -a查看 STATUS 列,docker logs <container>查最后一屏 | Up 2 minutes (unhealthy)或容器反复重启 | 检查对应服务的healthcheck.test命令是否能在容器内手动执行成功(如docker exec -it openclaw-mysql mysqladmin -uopenclaw -popenclaw123 ping) |
2. OpenClaw 日志中的Skill not found | tail -f ./logs/app.log | grep "Skill not found" | 机器人收消息但无响应,日志里有Skill not found: xxx-skill | 检查./skills/目录下 JAR 文件名前缀是否和robot.yaml的action字段完全一致(大小写、连字符);检查 JAR 是否损坏(jar -tf xxx-skill-1.0.0.jar | head -5) |
3.robot.yaml的 YAML 语法错误 | docker-compose up -d openclaw后,docker logs openclaw-app看是否有InvalidConfigException | OpenClaw 启动失败,日志第一行就报错Caused by: com.fasterxml.jackson.databind.JsonMappingException: Cannot construct instance of java.util.ArrayList | 用在线 YAML 验证器(如 https://yamlchecker.com/)粘贴robot.yaml,重点检查groups.id是否加了引号、缩进是否空格/Tab 混用 |
| 4. 飞书事件推送 403 错误 | 在飞书开放平台「机器人管理」→「事件订阅」→「查看推送记录」 | 推送记录里全是403 Forbidden,Last delivery time是空的 | 登录飞书开放平台,关闭该机器人的「IP 白名单」;检查robot.yaml的verificationToken是否和飞书后台显示的完全一致(32 位,区分大小写) |
| 5. MySQL 连接超时 | docker logs openclaw-app | grep "Connection refused" | OpenClaw 日志循环打印Cannot connect to database,docker ps看openclaw-mysql状态正常 | 检查docker-compose.yml里openclaw服务的depends_on是否写了mysql: condition: service_healthy;检查SPRING_DATASOURCE_URL的mysql:是否拼写正确(不是my-sql或mysql-db) |
| 6. Redis 连接拒绝 | docker logs openclaw-app | grep "Unable to connect" | OpenClaw 启动后立即报Cannot connect to redis:6379,但docker exec -it openclaw-redis redis-cli ping返回PONG | 检查docker-compose.yml里redis服务的command是否覆盖了默认端口(如误写redis-server --port 6380);检查openclaw服务的environment里SPRING_REDIS_HOST是否为redis(不是localhost或127.0.0.1) |
| 7. Nacos 配置未加载 | curl http://localhost:8848/nacos/v1/cs/configs?dataId=openclaw-robot&group=DEFAULT_GROUP | 返回空或{"code":404,"message":"config not found"} | 检查nacos-init.sql是否存在且内容正确;检查docker-compose.yml里nacos服务的volumes是否映射了./nacos-init.sql:/home/nacos/init.sql;检查SPRING_DATASOURCE_PLATFORM: mysql是否设置 |
这张表我贴在我们运维团队的共享文档首页,新人入职第一件事就是背熟它。实践证明,90% 的 OpenClaw 问题,5 分钟内就能按表索骥定位到根因。
最后分享一个个人体会:OpenClaw 的强大,不在于它有多炫酷的功能,而在于它把“自动化”的复杂度,降到了运维工程师能轻松掌控的水平。它不强迫你学 Kubernetes、不逼你写 Go 微服务、不让你啃 Spring Cloud 全家桶。你只需要懂 YAML、会写 Java、能 curl 测试,就能构建出企业级的告警协同体系。这正是它在众多开源项目中脱颖而出的原因——不是最先进,但一定是最务实。