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
羽毛球分组比赛记分
小程序二维码

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

小夜