Cron表示式轉systemd定時器工具

免費工具,將cron表示式(分 時 日 月 星期)轉換為systemd定時器的OnCalendar=語法。同時對日期與星期同時限定時的OR語義差異進行提示,適用於將cron任務遷移到Docker/Kubernetes環境。

cron欄位與systemd組成部分對照表

cron表示式的5個欄位與systemd的OnCalendar=語法對應關係如下。

位置 cron欄位 systemd對應部分
1 分鐘 時間部分的分鐘(HH:MM:SS中的MM)
2 小時 時間部分的小時(HH:MM:SS中的HH)
3 日(日期) 日期部分的日(年-月-日中的日)
4 日期部分的月(年-月-日中的月)
5 星期 星期字首(例如Mon、Mon..Fri)

由於cron沒有秒欄位,systemd的秒部分始終為"00"。當日期和月份均不受限(*)時,systemd的年-月-日部分可以完全省略。

cron星期編號與systemd星期縮寫對照表

cron用0〜7的數字表示星期,而systemd使用英文星期縮寫。

cron星期編號 systemd星期縮寫
0 (7) Sun
1 Mon
2 Tue
3 Wed
4 Thu
5 Fri
6 Sat

常見轉換示例

cron表示式 OnCalendar= 含義
* * * * * OnCalendar=*-*-* *:*:00 每分鐘執行一次(相當於cron的"* * * * *")。
*/15 * * * * OnCalendar=*:00/15:00 每15分鐘執行一次。
0 9 * * 1-5 OnCalendar=Mon..Fri 09:00:00 工作日(週一至週五)上午9點執行。
0 0 1 * * OnCalendar=*-*-01 00:00:00 每月1日0點執行。
0 0 1 1 * OnCalendar=*-01-01 00:00:00 每年1月1日0點執行。
0 0 1 * 1 OnCalendar=Mon *-*-01 00:00:00 同時指定日期(1日)與星期(週一)的示例。在cron中這是OR條件(滿足其一即可執行),但在systemd中會變為AND條件(必須同時滿足才執行),因此轉換結果的執行頻率會低於原cron表示式。

同時限定日期與星期(均不為"*")的cron表示式,無法通過systemd的OnCalendar語法準確轉換,因為cron在此情形下是OR語義,而systemd始終是AND語義。建議將此類情況拆分為兩個獨立的systemd定時器。

使用提示

  • 如果將日期與星期都設為非"*",cron的OR條件無法用systemd的AND條件準確表達。請檢視轉換結果中的警告,必要時拆分為兩個定時器。
  • 一些最小化的容器基礎映象(例如基於Alpine的Docker映象)根本不包含cron守護程序,此時systemd定時器是遷移計劃任務的實用替代方案。
  • 可以使用"systemd-analyze calendar"命令驗證生成的OnCalendar行,該命令還會顯示接下來的計劃執行時間。
  • 與單行crontab不同,systemd定時器由兩個檔案組成:.timer單元(計劃部分)和.service單元(實際執行的任務)。
  • 對於不同時組合日期與星期的簡單計劃(每小時、每天、每週等),本轉換結果始終是精確的。

常見問題

OnCalendar=的格式為"星期 年-月-日 時:分:秒"(星期和日期部分可省略)。"*"表示"任意值",".."表示範圍,"/"表示間隔,","用於列舉多個值。例如"Mon..Fri 09:00:00"表示工作日上午9點整。

systemd定時器提供了cron本身沒有的功能:通過journalctl集中管理執行日誌、等待依賴的服務先啟動、以及可配置的失敗自動重試。容器基礎映象也越來越傾向於不包含cron守護程序以保持輕量,因此在基於systemd的主機上,定時器成為自然的替代方案。

按照Vixie cron的語義,當日期與星期都被限定(非"*")時,只要滿足其中一個條件任務就會執行,即OR條件。而systemd的OnCalendar語法始終將星期和日期部分作為AND條件處理(必須同時滿足)。本工具會檢測到這種情況並顯示警告,提示轉換結果的執行頻率可能低於原cron表示式。

對於不同時組合日期與星期的簡單計劃,轉換結果是精確的。但如果出現了OR語義警告,實際執行頻率可能與預期不同,建議在部署到生產環境前使用"systemd-analyze calendar"命令確認接下來的計劃執行時間。

標準的5欄位cron表示式沒有秒欄位,因此生成的OnCalendar行中的秒部分始終為"00"。systemd的OnCalendar語法本身支援指定秒,但本工具從cron轉換時不會使用該功能。
ツールくん

閒話 ― 從cron到systemd定時器

systemd大約於2010年前後作為管理Linux啟動流程的初始化系統出現,此後成為大多數發行版的標準配置。其中的定時器功能與cron類似,提供週期性執行能力,但增加了cron從未擁有的功能:依賴關係解析、通過journalctl集中管理執行日誌,以及可配置的失敗重試行為。

與此同時,Docker和Kubernetes等容器環境中,為了保持映象體積小巧,越來越多的基礎映象根本不包含cron守護程序。當需要在此類環境中執行週期性任務時,現實的選擇要麼依賴Kubernetes CronJob等編排層面的機制,要麼在主機本身執行systemd的情況下交給systemd定時器處理。

OnCalendar=語法比cron的5個欄位表達能力更強,支援指定年份精度和秒級精度,但正因如此,一些cron表示式(同時限定日期與星期的OR條件)在簡單轉換下會改變含義。本工具明確地提示這一警告,正是為了讓遷移過程不至於陷入這個容易被忽略的陷阱。