OpenClaw 内置 Cron 原理

2026-05-06阅读 0热度 0
OpenClaw cron 定时任务

OpenClaw 定时任务(内置 Cron) 原理

揭开OpenClaw“定时任务”的面纱,其实它的核心机制并不复杂。简单来说,它就像在进程内部装了一个精巧的Cron表达式调度器。这个调度器会不间断地计算每个任务的“下一次触发时间”,一旦时间到了,它就会麻利地把任务投递到执行器(可能是线程池、协程或者队列)里去跑起来。整个过程自动化程度很高,可靠性也不错。

定时任务配置

OpenClaw自带了一套Cron调度系统,所有相关的配置数据都存储在.openclaw/cron这个目录下。

举个例子,你可能会看到类似/root/openclaw-docker/data/.openclaw/cron/jobs.json这样的路径。这通常是由“OpenClaw的数据目录(data dir)+ 固定的子目录.openclaw/cron/ + 固定的文件名jobs.json”这几部分组合而成的。

换句话说,真正需要你操心、可能变动的地方,通常只有前半段的数据目录路径,比如/root/openclaw-docker/data。至于后面的相对路径和文件名,多半是程序内部硬编码写死的。

判断这个 jobs.json 路径由哪里决定

想要精准定位jobs.json文件到底在哪,得从启动方式入手,顺藤摸瓜。

1) 看容器是怎么起的(compose 还是 docker run)

第一步,先看看所有容器的情况,重点观察容器名、镜像、启动命令和挂载信息。可以用下面这个命令,信息展示得比较清楚:

docker ps --format 'table {{.Names}}\t{{.Image}}\t{{.Command}}\t{{.Mounts}}'

2) 找到 openclaw 容器名后,导出完整启动/挂载信息

找到名字里带“openclaw”的容器后,比如可能是openclaw-docker-openclaw-gateway-1,接着用docker inspect命令深挖它的内情,关键看Binds或Mounts字段。把下面的容器名换成你实际查到的:

docker inspect openclaw-docker-openclaw-gateway-1 --format 'Name={{.Name}}Cmd={{json .Config.Cmd}}Entrypoint={{json .Config.Entrypoint}}Env={{json .Config.Env}}Binds={{json .HostConfig.Binds}}Mounts={{json .Mounts}}'

命令执行后,你可能会看到类似这样的输出:

Binds=["/root/openclaw-docker/data/.openclaw:/home/node/.openclaw:rw", ...]Mounts=[{"Type":"bind","Source":"/root/openclaw-docker/data/.openclaw","Destination":"/home/node/.openclaw", ...}]

这段输出信息量不小,我们来解读一下:它表明宿主机的目录/root/openclaw-docker/data/.openclaw,通过bind mount的方式,映射到了容器内部的/home/node/.openclaw路径。

而OpenClaw的Cron数据文件,就存放在.openclaw/cron/jobs.json这个相对路径下。这样一来,路径就非常明确了:

  • 在容器内部,文件位于:/home/node/.openclaw/cron/jobs.json
  • 在宿主机上,对应的文件就在:/root/openclaw-docker/data/.openclaw/cron/jobs.json

另外,环境变量(Env)的配置也值得留意,例如:

Env=["HTTP_PROXY=http://172.17.0.1:1080","TERM=xterm-256color","NODE_OPTIONS=--use-env-proxy","NO_PROXY=localhost,127.0.0.1,172.17.0.0/16,10.0.0.0/8","HOME=/home/node"

看到没?环境变量里设置了HOME=/home/node。很多程序都有个习惯,默认会把用户数据放在$HOME/.openclaw目录下,这就进一步印证了容器内确实会使用/home/node/.openclaw这个路径。

jobs.json 配置说明

理解了文件在哪,接下来看看它里面长什么样。下面是一个典型的jobs.json配置示例:

{
"version": 1,
"jobs": [{
"id": "UUID-EXAMPLE-0001",
"agentId": "main",
"name": "定时执行脚本任务(示例)",
"enabled": true,
"createdAtMs": 1700000000000,
"updatedAtMs": 1700003600000,
"schedule": {
"kind": "every",
"everyMs": 43200000},
"sessionTarget": "isolated",
"wakeMode": "next-heartbeat",
"payload": {
"kind": "agentTurn",
"message": "执行 bash /home/node//task.sh \"\" 2"},
"state": {
"nextRunAtMs": 1700043200000,
"lastRunAtMs": 1700003600000,
"lastStatus": "ok",
"lastDurationMs": 16204}}]
}

顶层

  • version: 文件格式的版本号,主要用于后续的兼容性检查和升级迁移。
  • jobs: 一个数组,里面包含了所有定义好的定时任务。

job 基本信息

这一部分描述了任务的身份和状态:

  • id: 任务的唯一标识符,通常是一个UUID,确保每个任务都是独一无二的。
  • agentId: 指定由哪个Agent来执行这个任务,比如示例中的main
  • name: 任务在界面上显示的名称,起个清晰的名字方便管理。
  • enabled: 一个布尔值开关。true表示启用,调度器会正常触发它;false则表示暂时关闭,不会被调度。
  • createdAtMs / updatedAtMs: 分别表示任务创建和最后更新的时间戳,单位是毫秒。

调度计划 schedule

这是定时任务的“大脑”,决定了它何时运行。示例中展示的是最简单的一种:

  • kind: "every": 表示按固定时间间隔重复触发,而不是用Cron表达式。
  • everyMs: 间隔的毫秒数。比如示例的43200000毫秒,换算一下就是12小时。

当然,OpenClaw的调度器不止这一种玩法,它支持三种主要的调度类型:

类型 说明 示例
at 一次性定时 “30分钟后提醒我”
every 固定间隔重复 “每5分钟检查一次”
cron 标准Cron表达式 0 9 * * 1-5(工作日每天9点)

如果想使用更灵活、更强大的Cron表达式,配置可以写成这样:

"schedule": {
"kind": "cron",
"expr": "55 9 3 * *",
"tz": "Asia/Shanghai"
}

字段说明

  • kind: "cron": 明确使用cron表达式来触发。
  • expr: "55 9 3 * *": 标准的五段式Cron表达式(分 时 日 月 周)。
  • tz: "Asia/Shanghai": 指定解释Cron表达式所使用的时区。这个设置非常重要,能有效避免因容器默认使用UTC时间而造成的执行时间偏差。

会话与唤醒

这部分配置决定了任务执行时的“环境”和“触发时机”:

  • sessionTarget: "isolated": 表示每次任务运行时,会启动一个独立的“隔离会话”。这样做的好处是,任务执行过程中的所有上下文和状态都被限制在这个独立环境里,不会污染到主对话或其他的任务上下文,非常适合执行一些复杂的、有副作用的操作。
  • wakeMode: "next-heartbeat": 指定唤醒执行的方式。意思是,当触发时间到达后,任务不会立即被拉起,而是要等到“下一次调度器心跳/调度周期tick”时才会执行。这种方式能合并调度检查,减少系统开销,但可能会引入轻微的、几乎可以忽略的延迟。

关于执行模式,通常有两种选择:

  • Main Session: 把任务当作一条“用户消息”直接注入到主对话中。效果就像你手动发了一条消息去触发Agent一样。适合简单、快捷的交互。
  • Isolated Session: 如上面配置所示,启动一个完全独立的会话来执行任务。这种模式特别适合那些需要联网搜索、调用外部工具、生成复杂报告等耗时较长的复杂任务。独立任务执行完毕后,可以选择将结果汇总汇报回主会话。

执行内容 payload

这里定义了任务被触发后,具体要做什么:

  • kind: "agentTurn": 表示将一条“消息回合”投递给指定的Agent来执行。这是最常见的一种任务类型。
  • message: 实际发送给Agent的指令文本。在示例中,就是一条执行Bash脚本并传递参数的命令。

需要注意的是,payload.kind也可以是其他类型。如果设置为systemEvent,那么任务触发时只是在OpenClaw界面里显示一条系统消息,而不会触发Agent执行具体操作。

运行状态 state(运行后写回)

这部分字段不是由你配置的,而是任务在每次运行后,由系统自动更新写回的,用于记录任务的历史执行情况:

  • nextRunAtMs: 根据调度计划计算出的下一次触发时间(毫秒时间戳)。
  • lastRunAtMs: 上一次任务实际被触发的时间。
  • lastStatus: 上一次执行的状态,比如示例中的ok表示成功。
  • lastDurationMs: 上一次任务执行所耗费的时间(毫秒)。

配置方式

那么,怎么创建这些定时任务呢?其实最简单的方式,就是直接和OpenClaw对话。你完全可以用自然语言说,比如“请帮我创建一个每周一早上9点检查系统状态的定时任务”。

OpenClaw在理解你的意图后,会自动在后台生成相应的Cron任务配置,并将数据持久化保存到我们前面提到的/home/node/.openclaw/cron目录中。整个过程非常直观,几乎不需要手动编辑JSON文件。

免责声明

本网站新闻资讯均来自公开渠道,力求准确但不保证绝对无误,内容观点仅代表作者本人,与本站无关。若涉及侵权,请联系我们处理。本站保留对声明的修改权,最终解释权归本站所有。

相关阅读

更多
欢迎回来 登录或注册后,可保存提示词和历史记录
登录后可同步收藏、历史记录和常用模板
注册即表示同意服务条款与隐私政策