dsh-cron-guard:一次扫描查清本机定时任务有没有停摆

前言

定时任务的问题往往不是跑失败,而是不跑了也没人知道:crontab 整行被注释掉、launchd 的日志路径失效、任务退出码长期为 1。这些都要等几天后发现数据没更新,才回头追查。DSH 的理念是「一切皆插件」,本机巡检也可以做成一个插件。下面介绍 feely0208/dsh-cron-guard(发布名 @deepwhale-cn/dsh-cron-guard),它把「本机这些定时任务到底还在不在跑」变成一次体检。

这是什么

由 feely0208 维护的 DSH 插件,定位是只读的定时任务守卫:扫描本机 launchd 与 cron 任务,判断哪些已经悄悄停摆、哪些根本没有留下运行证据。它不改 crontab、不写 plist、不重启任务、不联网、不上传数据。作者在 README 中明确把「不装会怎样」作为开篇:整条 crontab 被注释、日志路径失效、退出码一直为 1,都要等数据不更新才发现。

扫描范围

一次扫完以下位置:

  • ~/Library/LaunchAgents
  • /Library/LaunchAgents
  • 用户 crontab
  • Linux 下额外尽力读 /etc/crontab 和 /etc/cron.d/*

怎么判「在不在跑」

这是本插件的设计核心。README 的结论是:launchd 的 runs(累计运行次数)和 last exit code 才算「跑没跑」;日志 mtime 只证明「有没有留下证据」。

具体分两层:

1、对 launchd,通过 launchctl print gui/<uid>/<label> 读 runs / last exit code / job state;连续两次扫描 runs 不涨、且超过 N 个计划周期没有成功,才算停摆。
2、如果脚本被设计成「今日已发完就静默 exit 0」,日志会长期不更新,不会再被误判成停摆。
3、不写日志的任务可以配心跳文件,每次被触发覆盖写一行时间戳,心跳新鲜即算成功。

cron 没有 runs 可看,就按日志判断。

输出哪些证据

每个任务会给出:上次运行、上次成功、距上次成功多久、上次退出码、连续失败次数、日志尾部。日志尾部会自动脱敏 token、邮箱、口令。

插件还会识别几类真实坑:

  • #OLD- 这类被注释掉的任务
  • plist 缺 RunAtLoad / StartInterval / StartCalendarInterval / WatchPaths,导致永远不自动运行
  • 日志文件不存在或 0 字节(等于没留下证据)
  • Disabled=true
  • 空 plist 占位

三档结论与退出码

判定结果分四档,文本、--json、--md 三种输出:

档 情况
红(停摆) launchd runs 不涨且超过 N 个周期没成功;cron 按日志判断;#OLD- 注释任务;没有任何触发条件
黄(没证据 / 有失败) 日志文件不存在或 0 字节;上次退出码非 0;未加载、Disabled=true、空 plist;一次性任务日期已过但从未跑
灰(一次性) StartCalendarInterval 带 Year / 具体日期的一次性任务,日期已过且已跑过;只是说明,不用处理
通过 其余;输出里会带「判活依据」(runs / 退出码)

退出码:0 为正常、1 为有红、2 为只有黄。可以直接接进 CI 或巡检脚本。

安装与启用

在 DSH 中安装:

dsh plugin --profile web add @deepwhale-cn/dsh-cron-guard

装好后,侧栏会出现「定时任务守卫」面板,列表显示红/黄任务、「多久没成功」,并可切换阈值(2/3/5 个周期)。

CLI 也可以单独跑,不需要装进宿主,要求 Node ≥ 18:

node bin/cli.mjs                  # 扫本机真实任务
node bin/cli.mjs --json           # 给脚本用
node bin/cli.mjs --periods 3 --list
node bin/cli.mjs --help

配置项

配置文件 .cron-guard.json 按 cwd → ~ 顺序查找,也可以用 --config 指定:

{
  "periods": 2,
  "heartbeats": {
    "com.example.job": "~/path/job.last"
  },
  "successRe": "成功|RUN_OK",
  "failRe": "失败|error"
}

命令行等价写法:--heartbeat com.example.job=~/path/job.last(可重复)、--periods 3。

runs 快照默认写在 ~/Library/Application Support/dsh-cron-guard/state.json,只存 label + runs + 时间,不含任何业务数据;可以用 --no-state 关掉、用 DSH_CRON_GUARD_STATE 改路径。

测试与安全

跑测试:

bash tests/run.sh

测试只在 mktemp 目录里造 fixture(假 HOME + 假 crontab + 假 launchctl 输出),不读真实 crontab、不联网。

适用场景与注意

适合在本机跑 launchd / cron 定时任务、希望及早发现「静默停摆」的开发和运维场景。插件的扫描、判定都以当前 dsh 进程权限为准,能看到多少任务取决于运行身份;安装前应先检查源码与许可证(仓库标注为 MIT)再决定要不要用。

结尾

dsh-cron-guard 补上的不是「任务怎么配」,而是「配好的任务还在不在跑」。目录页与源码见:

  • 目录页:https://www.skillhub.cn/plugins/feely0208/dsh-cron-guard
  • GitHub:https://github.com/feely0208/dsh-cron-guard
羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜