只用 0 3 * * 1-5 一行,就能表達「平日凌晨 3 點執行」這樣的排程——這就是 Cron 表達式的威力。從 Linux 的 crontab 到 GitHub Actions、Kubernetes CronJob、各種雲端排程器,定期執行的世界幾乎都靠這套語法運作。

Cron 表達式撰寫完全指南:用實例理解 5 個欄位與特殊字元

本文將 Cron 的五個欄位與特殊字元,把實際的表達式與其含義配對逐一整理。文末還整理了現場容易踩到的陷阱與常見問題。

Cron 表達式的基本結構:五個欄位

標準 crontab 的 Cron 表達式由以半形空格分隔的五個欄位組成。

┌───────────── 分        (0 - 59)
│ ┌───────────── 時      (0 - 23)
│ │ ┌───────────── 日    (1 - 31)
│ │ │ ┌───────────── 月  (1 - 12)
│ │ │ │ ┌───────────── 星期 (0 - 7, 0 和 7 為星期日)
│ │ │ │ │
* * * * *

各欄位可取的值範圍如下。

欄位範圍備註
0–59
0–230 為午夜,23 為 23 時
1–31月份中的日期
1–12也可用 JANDEC(視實作而定)
星期0–70 和 7 為星期日,1 為星期一;也可用 SUNSAT

備註: GitHub Actions 與 Kubernetes 基本上也是這套 5 欄位格式。而 Quartz 與 AWS EventBridge 會加上「秒」或「年」形成 6~7 欄位格式,因此需要下文介紹的 ?L 等特殊字元。

用實例理解特殊字元

Cron 表達式的表現力來自各欄位可寫的特殊字元

符號含義範例讀作
*所有值* * * * *每分鐘
,列舉值0 9,12,18 * * *每天 9 時、12 時、18 時
-範圍0 9-17 * * *每天 9 時~17 時的每個整點
/間隔(步進)*/15 * * * *每 15 分鐘
?不指定(日/星期用)0 0 ? * MON每週一 0 時
L最後(last)0 0 L * *每月最後一天 0 時
W最近的平日0 0 15W * *最接近 15 日的平日
#第 n 個星期幾0 9 ? * MON#1第一個星期一 9 時

請注意 ?LW# 是 Quartz 系排程器(Spring、Jenkins、EventBridge 等)的擴充,標準 crontab 無法使用。

/(步進)的讀法

*/15 代表「從 0 開始,每隔 15」,也就是 0,15,30,45。與範圍組合可以指定起始位置。

*/15 * * * *     → 0,15,30,45 分(每 15 分鐘)
5/10 * * * *     → 5,15,25,35,45,55 分(從 5 分起每 10 分鐘)
0 9-17/2 * * *   → 9,11,13,15,17 時(9~17 時每 2 小時)

常用排程範例

可直接複製使用、現場最常出現的模式。

想做的事Cron 表達式
每分鐘* * * * *
每 5 分鐘*/5 * * * *
每小時整點0 * * * *
每天午夜0 0 * * *
每天上午 9 時 30 分30 9 * * *
平日凌晨 3 時0 3 * * 1-5
平日 9~18 時每 30 分鐘*/30 9-18 * * 1-5
每週一上午 9 時0 9 * * 1
每月 1 日午夜0 0 1 * *
每月最後一天午夜(Quartz 系)0 0 L * *
第一個星期一上午 9 時(Quartz 系)0 9 ? * MON#1

現場容易踩到的陷阱

1. 同時指定「日」與「星期」會變成 OR 條件

0 0 1 * 1 代表「1 日 或 星期一的午夜」,而不是「當 1 日是星期一時」的 AND 條件。由於違反直覺,建議只指定其中一個,另一個留 *(Quartz 系用 ?)較安全。

2. 時區取決於執行環境

許多 cron 使用伺服器時區,而容器與 CI 常以 UTC 運行。即使寫 0 0 * * *,也可能在 UTC 0 時(=台灣時間上午 8 時)執行,而非當地午夜。若想在台灣時間(UTC+8)凌晨 2 時執行,UTC 基準為 0 18 * * *

3. 將分欄位設為 * 會每分鐘執行

* 3 * * *(本想「每天 3 時執行一次」)實際上會在3 時這一小時內執行 60 次。若要「3 點整執行一次」,請用 0 3 * * *

4. 間隔過短造成重複執行

若每 5 分鐘的工作未在 5 分鐘內完成,下一次會在前一次仍在執行時啟動,造成多重執行。請設定有餘裕的間隔,或考慮加上鎖(lock)機制。

用工具消除「存檔前的不安」

Cron 表達式需要熟練才能讀寫,上述陷阱也難以用肉眼察覺。Cron 表達式解析器 能將你輸入的 Cron 表達式轉換成自然語言說明,並模擬接下來的執行時間,讓你在部署前一眼驗證「是否真的是想要的排程」。

常見問題

Cron 表達式的星期,0 和 7 哪個是星期日?

多數實作中 0 和 7 都指星期日。星期一是 1,星期六是 6。為避免混淆,在支援的環境中建議使用 SUNMON 這類英文三字母表記。

「每月最後一天」要怎麼寫?

在支援 L 的環境(Quartz、EventBridge)中可用 0 0 L * * 表達。標準 crontab 沒有 L,因此需要替代方案:在月底候選日(28~31 日)執行並在腳本中判斷日期,或以程式計算。

UTC 與當地時間的差異要怎麼處理?

從當地時間的時欄位減去 UTC 偏移量。台灣時間為 UTC+8,凌晨 2 時換算為 UTC 為前一天 18 時,即 0 18 * * *。若排程器支援明確指定時區,使用它最為可靠。

*/50/5 是一樣的嗎?

在分欄位中兩者實質相同(「每 5 分鐘」:0,5,10,…)。*/5 表示「整個範圍以 5 為步進」,0/5 表示「從 0 起以 5 為步進」。當你想偏移起點時(例如 7/15),明確的起始指定就派得上用場。