fixmint
ZH-TW

如何逐欄讀懂 cron 表達式

作者: · · 閱讀約 5 分鐘

cron 表達式是一行簡短的文字,用來告訴排程器何時執行工作。常見格式有五個欄位,以空格分隔:分鐘、小時、日、月、星期。這一行 0 9 * * 1-5 的意思是週一到週五的 09:00。每個欄位可以是數字、名稱、清單、範圍或間隔,或用 * 代表所有數值。當所有欄位都符合時,工作就會執行。

Cron 表達式解讀器Cron 排程執行時間不對免費使用

五個欄位

欄位可用數值範例
分鐘0 到 5930 代表每小時的第 30 分鐘
小時0 到 239 代表 09:00,採用 24 小時制
日1 到 3115 代表每月 15 日
月1 到 12,或 JAN 到 DEC3 或 MAR 代表三月
星期0 到 6,或 SUN 到 SAT0 或 SUN 代表星期日,1 代表星期一

有些系統也接受 7 代表星期日,但並非所有系統都支援,所以建議使用 0 或 SUN。這種格式的 cron 沒有秒的欄位,因此最小的間隔是一分鐘。

清單、範圍、間隔與名稱

  • 代表該欄位的所有數值。 * * * * 代表每分鐘執行。
  • 清單用逗號分隔。0 9,17 * * * 代表每天 09:00 和 17:00 執行。
  • 範圍用連字號。星期欄位中的 1-5 代表週一到週五。
  • 間隔用斜線。分鐘欄位中的 */15 代表 0、15、30 和 45 分。10-30/5 代表 10、15、20、25 和 30 分。
  • 名稱如 MON-FRI 可以取代數字,比較容易閱讀,前提是排程器支援。

這些寫法可以組合。0 8-18/2 * * * 代表從 08:00 到 18:00 之間,每隔兩小時的整點執行。

常見排程

表達式意思
* * * * *每分鐘
/15 * * *每 15 分鐘
0 * * * *每小時的第 0 分鐘
0 2 * * *每天 02:00
0 9 * * 1-5週一到週五的 09:00
0 9,17 * * *每天 09:00 和 17:00
30 6 1 * *每月 1 日的 06:30
0 0 * * 0每週日的午夜
0 0 1 1 *1 月 1 日的午夜
/5 9-17 * 1-5週一到週五,從 09:00 到 17:55 每 5 分鐘一次

請注意,0 0 * * 是午夜,0 12 * * 是中午。弄錯小時是最常見的錯誤之一。

日與星期

當「日」和「星期」兩個欄位都有限定時,只要其中任一符合,工作就會執行。這是 Vixie cron 以及許多由它衍生的系統所採用的經典規則。因此 0 0 13 * 5 會在每月 13 日的午夜執行,也會在每個星期五執行。很多人以為只會在「十三日的星期五」執行,結果執行次數比預期多。

如果兩個欄位之一是 *,就只有另一個欄位會生效。若要在星期五且為 13 日時執行,可以為每個星期五排程,並在腳本中檢查日期。其他排程器,包括部分雲端服務,可能採用不同規則,請參閱它們的說明文件。

時區與日光節約時間

cron 依照執行它的機器或服務的時鐘運作,通常就是該機器的當地時區。設定為 02:30 的工作,會在該時鐘的 02:30 執行。請先確認時區(在 Linux 上,執行 date 可以查看)。如果希望工作在各處都依照同一個時鐘執行,許多團隊會把伺服器設為 UTC,部分排程器也允許為每個工作指定時區。

日光節約時間每年會把時鐘調整兩次。春季時,許多地區會從 02:00 直接跳到 03:00,因此設定在 02:30 的工作沒有可執行的時間。秋季時,01:00 到 01:59 這一小時會出現兩次。各排程器對這些情況的處理方式不同:有些會跳過工作,有些只執行一次,有些則執行兩次。如果時間差異對你很重要,請讓工作避開清晨的時間調整區段,或改用 UTC。

六個欄位與 Quartz

有些排程器會在最前面加上秒的欄位,所以 /10 * * * * 代表每 10 秒執行一次。Java 的 Quartz 排程器使用秒、分、時、日、月、星期,以及選填的年份,並另外提供四個特殊字元:

  • ? 代表「不指定」。Quartz 要求日或星期其中一個欄位必須使用它,取決於你沒有設定的那一個。
  • L 代表最後。日欄位中的 L 是當月最後一天,星期欄位中的 6L 是最後一個星期五。
  • W 代表最近的工作日。15W 是最接近 15 日的工作日,而且不會跨到另一個月。
  • # 代表第 n 個星期幾。6#3 是第三個星期五。

Quartz 的星期編號與五欄位格式不同。它的 1 是星期日,7 是星期六,所以週一到週五要寫成 2-6,而不是 1-5。複製任何表達式之前,請先確認你的排程器採用哪一種格式。

常見錯誤

  • 分鐘欄位使用 */7。數值會是 0、7、14……直到 56。下一個會是 63,但這個數值不存在,所以 56 之後的執行會落在下一小時的第 0 分鐘。間隔只差四分鐘,而且間距不平均。請使用能整除 60 的間隔,例如 5、10、15 或 30。
  • 2 月 30 日。這個日期不存在,所以 0 0 30 2 * 永遠不會執行。在只有 30 天的月份使用 31 日也是同樣的情況。依照「任一符合」規則,星期的限定仍可能讓工作在其他日子執行,因此請檢查結果。
  • 小時 24 或分鐘 60。這些數值都超出範圍。多數排程器在儲存時就會拒絕,但並非全部都會。
  • 以為有秒的欄位。五欄位的表達式只會在整分鐘執行。
  • 把 cron 和正規表示式搞混。在 cron 中, 代表所有數值。在正規表示式中, 代表重複前一個項目。若要測試模式,請使用正規表示式測試器,並將 cron 表達式分開處理。

檢查接下來的執行時間

在依賴一個排程之前,請先用白話讀出這一行的意思,並列出接下來幾次的執行時間。cron 解讀器可以同時完成這兩件事,是最快找出「任一符合」規則或奇怪間隔的方法。

快速解答

第一個欄位是分鐘還是秒?

在標準的五欄位格式中是分鐘。只有部分六欄位的排程器會加上秒,而且秒會放在最前面。

為什麼我的工作在星期五執行,也會在 13 日執行?

因為日和星期兩個欄位都有設定,所以只要其中一個符合,工作就會執行。如果只想讓其中一個欄位生效,請將另一個欄位設為 *。

cron 使用 UTC 嗎?

只有當機器或服務設定為 UTC 時才是。否則會使用該系統的當地時區。

借助 AI 協助,由英文原文翻譯而成。

留言

    還沒有留言,搶先留言吧。

    您的評分(選填)

    您的電子郵件不會顯示,也不會被保存。

    Agentic AI in the Browser 的封面Agentic AI in the Browser

    隱私優先、在瀏覽器內執行的 AI 工作流程應用案例,也就是 fixmint 所依循的「在自己裝置上完成」理念。

    $4.99在 Gumroad 購買英文版