READMESource: main@8193b380
dsh-cron-guard · 定时任务守卫
不装会怎样
定时任务最坑的不是跑失败,是不跑了也没人知道。crontab 整条被注释、launchd 的日志路径失效、任务退出码一直是 1——都要等几天后发现数据没更新才追查。这个插件把「本机这些定时任务到底还在不在跑」变成一次体检。
它做什么
- 一次扫完:
~/Library/LaunchAgents、/Library/LaunchAgents、用户 crontab(Linux 额外尽力读/etc/crontab、/etc/cron.d/*)。 - 判「停摆」:超过 N 个计划周期没有一次成功(默认 N=2,可
--periods改)→ 红。 - 看「证据」:上次运行 / 上次成功 / 距上次成功多久 / 上次退出码 / 连续失败次数 / 日志尾部(自动脱敏 token、邮箱、口令)。
- 识别真实坑:
#OLD-这类被注释掉的任务、plist 缺RunAtLoad/StartInterval/StartCalendarInterval/WatchPaths导致永不自动运行、日志文件不存在或 0 字节(没留下证据)、Disabled=true、空 plist 占位。 - 三档结论:红 / 黄 / 通过;文本、
--json、--md三种输出,退出码 0 正常 / 1 有红 / 2 只有黄。 - 只读:不改 crontab、不写 plist、不重启任务、不联网、不上传。
面板:侧栏「定时任务守卫」→ 红/黄列表 + 「多久没成功」+ 阈值切换(2/3/5 个周期)。
安装
dsh plugin --profile web add @deepwhale-cn/dsh-cron-guard
CLI 也可以单独跑(不装进宿主也行,Node ≥ 18):
node bin/cli.mjs # 扫本机真实任务
node bin/cli.mjs --json # 给脚本用
node bin/cli.mjs --periods 3 --list
node bin/cli.mjs --help
怎么判「在不在跑」
launchd 的 runs(累计运行次数)和 last exit code 才算「跑没跑」;日志 mtime 只证明「有没有留下证据」。
- 判活:
launchctl print gui/<uid>/<label>读runs/last exit code/job state; 连续两次扫描runs不涨、且超过 N 个周期没有成功 → 才算停摆。 - 脚本设计成「今日已发完就静默
exit 0」时日志会长期不更新,不会再被误判成停摆。 - 不写日志的任务可以配心跳文件(每次被触发覆盖写一行时间戳),心跳新鲜即算成功。
分档
| 档 | 情况 |
|---|---|
| 🔴 红(停摆) | launchd runs 不涨 + 超过 N 个周期没成功;cron 没有 runs 可看,按日志判断;#OLD- 注释任务;没有任何触发条件 |
| 🟡 黄(没证据 / 有失败) | 日志文件不存在或 0 字节(不等于停摆);上次退出码非 0;未加载、Disabled=true、空 plist;一次性任务日期已过但从未跑 |
| ⚪ 灰(一次性) | StartCalendarInterval 带 Year/具体日期的一次性任务,日期已过且已跑过;只是说明,不用处理 |
| ✅ 通过 | 其余;输出里会带「判活依据」(runs / 退出码) |
配置(可选)
.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(可用 --no-state 关掉、DSH_CRON_GUARD_STATE 改路径);只存 label + runs + 时间,不含任何业务数据。
测试
bash tests/run.sh
只在 mktemp 目录里造 fixture(假 HOME + 假 crontab + 假 launchctl 输出),不读真实 crontab、不联网。
No comments yet. Be the first to write one.