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單元(實際執行的任務)。
- 對於不同時組合日期與星期的簡單計劃(每小時、每天、每週等),本轉換結果始終是精確的。
常見問題
閒話 ― 從cron到systemd定時器
systemd大約於2010年前後作為管理Linux啟動流程的初始化系統出現,此後成為大多數發行版的標準配置。其中的定時器功能與cron類似,提供週期性執行能力,但增加了cron從未擁有的功能:依賴關係解析、通過journalctl集中管理執行日誌,以及可配置的失敗重試行為。
與此同時,Docker和Kubernetes等容器環境中,為了保持映象體積小巧,越來越多的基礎映象根本不包含cron守護程序。當需要在此類環境中執行週期性任務時,現實的選擇要麼依賴Kubernetes CronJob等編排層面的機制,要麼在主機本身執行systemd的情況下交給systemd定時器處理。
OnCalendar=語法比cron的5個欄位表達能力更強,支援指定年份精度和秒級精度,但正因如此,一些cron表示式(同時限定日期與星期的OR條件)在簡單轉換下會改變含義。本工具明確地提示這一警告,正是為了讓遷移過程不至於陷入這個容易被忽略的陷阱。