跳到主要内容

定时任务模块 (Scheduler)

SayClaw 定时任务模块基于 robfig/cron/v3 构建,实现实例健康监控、日志自愈、用量同步、资源采集等全自动化运维。

最后更新:2026-03-06


架构

所有任务逻辑集中在 admin-api/cmd/server/scheduler.go,随主进程启动。

admin-api (Go)
├── scheduler.go ← cron 注册 + 所有 Job 实现
├── scheduler_api.go ← 管理 API(/job-runs /task-queue /usage-daily)
└── task_queue (MySQL) ← 事件驱动队列(apply_marketplace_item / init_instance 等)

数据库表

表名用途
task_queue事件驱动异步任务队列
job_runscron 任务执行历史
server_metrics服务器资源快照(CPU/内存/磁盘)
usage_daily实例每日 Token 用量汇总

当前任务清单

#任务名触发方式频率状态说明
1queueWorkercron每 5 秒✅ 运行中扫 task_queue 并执行异步任务
2health_checkcron每 5 分钟✅ 运行中SSH 检查服务状态 + HTTP fallback;更新 health_status
3auto_recoverycron每 10 分钟✅ 运行中fail_count ≥ 3 的实例自动 SSH restart
4log_scancron每 5 分钟✅ 运行中扫描实例日志 + 主动端口/TG配置检测,发现错误自动修复(见下文)
5server_metricscron每 5 分钟✅ 运行中SSH 采集 CPU/内存/磁盘,写 server_metrics
6token_usage_synccron每 15 分钟✅ 运行中从 chat_messages 同步 Token 用量到 usage_daily
7key_validity_checkcron每 30 分钟✅ 运行中验证 LiteLLM virtual key 有效性,修复 auth-profiles.json 不一致
8key_balance_alertcron每小时⏸️ 暂停Key 余额 < 阈值时 TG 告警(P2)

事件驱动任务(task_queue)

任务类型触发时机说明
init_instance用户认领实例(POST /me/instances/claimSSH 写 openclaw.json + BOOTSTRAP.md,重启服务
apply_marketplace_item用户安装应用市场项目SSH 写技能/配置文件,清 session 缓存,重启,更新 install_count
sync_models管理员触发模型同步将 ai_models 表的模型列表同步到实例 openclaw.json

log_scan — 日志自动巡检 + 自愈(9 条规则)

log_scan5 分钟 SSH 读取每个实例近 5 分钟的 journalctl 日志,同时主动检测端口监听状态和配置文件完整性,匹配以下错误模式并自动修复:

#检测方式错误特征根因自愈动作
日志关键词No API key found for provider "litellm"auth-profiles.json 损坏或 key 丢失从 DB oc_api_keys 取 key → 重写文件 → stop + kill port + start
日志统计exit-code 1 出现 ≥ 3 次openclaw.json 配置异常运行 openclaw doctor --fix → restart
日志关键词ENOMEM / out of memory内存耗尽标记 health_status=unhealthy(需人工介入)
日志关键词Config invalid + Unrecognized keyopenclaw.json 含不支持字段(如 controlUi.portpython 删除 controlUi 中未知字段 → restart
主动读配置文件openclaw.json 含 auth.profiles 字段auth.profiles 覆盖 auth-profiles.json 导致 key 找不到python 删除 auth.profiles 字段 → stop + kill port + start
日志关键词another gateway instance is already listening端口被其他进程(如 browser control)占用kill 占用 PID → stop + start
主动检测端口service=active 但端口未在 0.0.0.0 监听gateway 实际未绑定外网,TG Bot 无法接收消息kill 占用 PID → stop + start
日志统计API rate limit reached ≥ 3 次API 调用超速率限制标记 health_status=rate_limited(只告警,不自动切模型)
主动读 openclaw.jsonchannels.telegram.enabled=falsebotToken 缺失OpenClaw 覆写 openclaw.json 时把 TG 配置清空从 DB sayclaw_portal.user_instances 取 bot token → 写回 openclaw.json → restart

规则 ⑦ 是 TG 不回消息的主动防护:即使 systemd 状态为 active,若端口未在 0.0.0.0 监听,TG 消息无法到达,log_scan 会在 5 分钟内发现并修复。

规则 ⑨ 防止 OpenClaw 自动 config migration 覆写文件时意外清空 TG Bot 配置,确保用户绑定的 Bot 始终在线。

修复结果写入 job_runs,可在 Admin 后台「调度管理」→「Job 执行记录」查看。


key_validity_check — Key 一致性检查

每 30 分钟验证:

  1. LiteLLM 中 virtual key 是否有效(GET /key/info
  2. 实例 auth-profiles.json 中的 key 是否与 DB oc_api_keys 一致
  3. 若不一致 → 重写 auth-profiles.json → restart 服务

关键流程:认领 → 自动初始化

用户 POST /me/instances/claim

① INSERT user_instances
② INSERT task_queue { type: "init_instance" }
↓ (< 10s,queueWorker 拉取)
③ SSH 写 openclaw.json(dmPolicy + allowFrom)
④ SSH 写 BOOTSTRAP.md(引导 AI 完成个性化设置)
⑤ systemctl stop + fuser -k PORT + systemctl start
⑥ task_queue.status = 'done'

health_check 策略

SSH 优先,HTTP fallback:

serviceName != "" && serverID != ""
→ SSH: systemctl is-active SERVICE
→ 若 SSH 不通 → HTTP: GET ws://HOST:PORT(超时 5s)
→ SSH 通但服务 inactive → 立即标记 unhealthy(不走 HTTP)

另增 Layer 2:LiteLLM key 验证(GET /key/info?key=RAW_KEY),key 失效时 health_status = key_invalid


已知问题与处理记录

Browser Control 端口冲突(2026-03-06)

背景:OpenClaw v2026.3.2 的 Browser Control 会在 gateway_port + 2 上绑定 127.0.0.1。若多个实例端口连续分配(如 18790、18791、18792…),相邻实例的 browser control 端口会与下一个实例的 gateway 端口冲突,导致 TG Bot 无法连接。

根治方案:实例端口间距 ≥ 10,彻底避开冲突。

当前小二(ai-jp-2)端口分配

实例Gateway 端口Browser Control 端口
011878918791
021881018812
031882018822
041883018832
051884018842
061885018852
071886018862
081887018872
091888018882
101879818800

当前小三(ai-jp-3)端口分配

实例Gateway 端口Browser Control 端口
011891018912
021892018922
031893018932
041894018942
051895018952
061896018962
071897018972
081898018982

log_scan 规则 ⑦ 会主动检测该类问题并在 5 分钟内自动修复。

OpenClaw v2026.3.2 配置变更(2026-03-06)

升级到 v2026.3.2 后,以下字段格式发生变化:

字段旧格式新格式
Gateway tokengateway.tokengateway.auth.token
Gateway mode无需指定必须设置 gateway.mode=local 或启动参数加 --allow-unconfigured

小三实例启动参数(ExecStart)均已加 --allow-unconfigured 以规避 config migration 覆写问题。

远程 LiteLLM 路由(小三实例)

小三(ai-jp-3)上无本地 LiteLLM,需连接小龙(35.243.76.69:4000)。

现状:小三实例直接使用 Anthropic / OpenAI 真实 API key,不经过 LiteLLM。

实例auth providerprimary model
jp3-01 ~ jp3-08anthropic + openaianthropic/claude-sonnet-4-6

原因:OpenClaw 的 litellm/ provider 前缀会把模型名原样(含前缀)发给 LiteLLM,而 LiteLLM 不接受带 litellm/ 前缀的模型名,导致 Unknown model 错误。LiteLLM /v1/messages(Anthropic 格式)接口也未开放,因此改用直连 API key 方案。


Admin UI

admin.sayclaw.ai → 侧边栏「调度管理」,三个 Tab:

Tab内容刷新频率
Job 执行记录health_check / log_scan / token_usage_sync 等运行历史30s 自动刷新
任务队列init_instance / apply_marketplace_item 等异步任务状态15s 自动刷新
Token 使用统计各实例每日 Token / 请求 / 费用(usage_daily 表)手动刷新

术语统一补充(2026-03-05)

  • 优先统一使用 task_queue 作为后台异步任务主表命名。
  • 状态机统一:pending -> running -> done|failed,失败可重试。