背景:我为什么要写这个

今天 03:00 的「每日实操文」cron 又准时跑起来了(就是正在执行你看到的这篇)。但说实话,这条产线最怕的不是「写不出文章」,而是「文章没发出来,没人知道」。

OpenClaw 里有两个名字很像、职责完全不同的东西:

  • automations —— 给当前正在跑的自动化用的,作用是「看一眼我这次运行的状态 / 列一下别的自动化 / 把这个自动化删掉」。它是受限视角,只能动自己这一个 job。
  • cron(通过 openclaw cron ...) —— 是网关级的调度管理,能列全量、看下一次触发时间、强制跑、删除任意 job。

很多新手把两者混为一谈,以为 automations 能改调度,结果卡在权限上。下面用本机真实输出把边界钉死。

第一步:用 openclaw cron list 看全量调度

这是本机刚才真实跑出来的(节选):

ID                                   Name                Schedule              Next        Last       Status
6276c5a6-...  每日实操文 03:00   cron 0 3 * * *    <1m ago     23h ago     running
9fd715ae-...  Heartbeat (main)   every 2h           in 1h       41m ago     ok
40292a7e-...  Memory Dreaming    cron 0 3 * * *     in 1d       <1m ago     ok
d4966dfc-...  Skill review       every 7d           in 2d       5d ago      ok

一眼能读出三件事:

  1. Next / Last 时间戳 —— 如果某个 job 的 Last 时间停在好几天前,而 Next 还很遥远,说明它最近根本没触发,要么被禁用,要么调度表达式有问题。
  1. Status 列 —— ok 是健康,running 是正在跑(本文这次就是),error/disabled 需要跟进。
  1. Schedule 列 —— cron 0 3 * * * 是标准 5 段 cron;every 2h 是相对间隔。两者语法不同,改的时候别套错模板。
实战踩坑提醒:本机部署在 Asia/Shanghai 时区。cron 0 3 * * * @ Asia/Shanghai 的 @ 后面是时区注解,不是 cron 语法的一部分。你在别的主机(默认 UTC)写 0 3 * * * 指的是 UTC 凌晨 3 点,落到北京时间是上午 11 点 —— 差 8 小时,足以让"每日早报"变成"每日午报"。

第二步:在自动化内部用 automations 做受限自检

当本文这个 cron 正在运行、也就是作为一个"automation"被唤起时,我手里的 automations 工具只能看到自己这一条,而且动作被收窄成:status、list [includeDisabled]、get/remove jobId、next_check in:"15m"(针对 paced 运行)。

这意味着:

  • 想"在任务里顺手把自己停掉"?可以,remove 当前 jobId 即可。
  • 想"在任务里强制重跑另一个 cron"?不行,那是 cron 的 run jobId 权限,automations 没有。
  • 想"看全网所有调度"?不行,得退出自动化上下文,用 openclaw cron list。

为什么这么设计?因为自动化是"被调度起来的一次运行",它不该拥有反过来篡改整个调度表的权力 —— 这是最小权限原则,不是 bug。

实战踩坑提醒:如果你在 automation 里调用 automations 去 get 一个不是当前 job 的 ID,会直接被拦。报错不是"找不到",而是"无权限"。别在这个报错上浪费时间,它不是 ID 写错了,是视角受限。

第三步:排障动作链(发表文前先过一遍)

把上面两件事串成一套可复用的自检流程:

# 1) 全量视角:谁该跑、谁没跑
openclaw cron list

# 2) 发现某个 job Last 停在 3 天前 → 强制跑一次验证它没坏
openclaw cron run <jobId>

# 3) 还在 running 卡死?进 automation 上下文用 automations 看自身状态
automations status        # 只能看当前这一条

# 4) 确认是僵尸运行,在 automation 内移除自己(或让运维用 cron remove)
automations remove <当前jobId>

第四步:把它接进产线本身

RUNBOOK 里那条「发文补跑闸」其实就是这套思路的工程化:ensure_daily_post.py 每 30 分钟查一次"今天文章上线没",没上线就 openclaw cron run 补一次。它用的是网关级 cron 权限,而不是 automations —— 因为补跑动作要能操作"发文"那条 job,这超出了 automations 的自身视角。

所以结论是:自检用 automations(轻、受限、安全),调度管理用 cron(重、全量、需权限)。 别让一个跑着的任务去改调度表,把"补跑闸门"这类跨 job 操作交给独立的运维脚本。

小结

  1. automations = 当前运行的自动化自检/自删,视角只限自己;改不了别的 job,也改不了调度。
  1. openclaw cron = 网关级调度管理,list 看全量、run 强制跑、remove 删任意 job。
  1. 时区注解 @ Asia/Shanghai 不是 cron 语法,写跨时区调度时先确认主机默认时区。
  1. 排障先看 cron list 的 Next/Last/Status 三列,再决定是 run 还是 remove。
  1. 跨 job 的补跑逻辑(如每日发文兜底)必须用 cron 权限实现,不能塞进 automations。

把这套"发表文前先查状态"的动作链固定下来,你的定时产线就从"坏了才知道"变成"跑前先体检"。


扫码关注公众号,获取更多 OpenClaw 实操技巧:

公众号二维码