Tools mentioned in this article
Open the browser-based tool while you read and try the workflow immediately.
只用 0 3 * * 1-5 一行,就能表達「平日凌晨 3 點執行」這樣的排程——這就是 Cron 表達式的威力。從 Linux 的 crontab 到 GitHub Actions、Kubernetes CronJob、各種雲端排程器,定期執行的世界幾乎都靠這套語法運作。

本文將 Cron 的五個欄位與特殊字元,把實際的表達式與其含義配對逐一整理。文末還整理了現場容易踩到的陷阱與常見問題。
Cron 表達式的基本結構:五個欄位
標準 crontab 的 Cron 表達式由以半形空格分隔的五個欄位組成。
┌───────────── 分 (0 - 59)
│ ┌───────────── 時 (0 - 23)
│ │ ┌───────────── 日 (1 - 31)
│ │ │ ┌───────────── 月 (1 - 12)
│ │ │ │ ┌───────────── 星期 (0 - 7, 0 和 7 為星期日)
│ │ │ │ │
* * * * *
各欄位可取的值範圍如下。
| 欄位 | 範圍 | 備註 |
|---|---|---|
| 分 | 0–59 | |
| 時 | 0–23 | 0 為午夜,23 為 23 時 |
| 日 | 1–31 | 月份中的日期 |
| 月 | 1–12 | 也可用 JAN–DEC(視實作而定) |
| 星期 | 0–7 | 0 和 7 為星期日,1 為星期一;也可用 SUN–SAT |
備註: 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 時 |
請注意 ?、L、W、# 是 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。為避免混淆,在支援的環境中建議使用 SUN、MON 這類英文三字母表記。
「每月最後一天」要怎麼寫?
在支援 L 的環境(Quartz、EventBridge)中可用 0 0 L * * 表達。標準 crontab 沒有 L,因此需要替代方案:在月底候選日(28~31 日)執行並在腳本中判斷日期,或以程式計算。
UTC 與當地時間的差異要怎麼處理?
從當地時間的時欄位減去 UTC 偏移量。台灣時間為 UTC+8,凌晨 2 時換算為 UTC 為前一天 18 時,即 0 18 * * *。若排程器支援明確指定時區,使用它最為可靠。
*/5 和 0/5 是一樣的嗎?
在分欄位中兩者實質相同(「每 5 分鐘」:0,5,10,…)。*/5 表示「整個範圍以 5 為步進」,0/5 表示「從 0 起以 5 為步進」。當你想偏移起點時(例如 7/15),明確的起始指定就派得上用場。