揭開 Cron 表達式的神秘面紗:排程任何事情
你需要每晚凌晨 3 點執行資料庫備份,或每週一早上傳送報告,或每 15 分鐘清除快取。在 Linux 和 Unix 伺服器上,執行這類任務的工具是 cron,而告訴 cron 何時執行某項任務的方式就是使用 cron 表達式。
Cron 表達式初看令人望而生畏。0 3 * * * 或 */15 9-17 * * 1-5 如果你不了解規律,看起來就像天書。但一旦你理解了這五個欄位,語法其實出奇地簡單。
五個欄位
每個標準 cron 表達式恰好有五個欄位,以空格分隔。每個欄位代表一個時間單位:
┌───────────── 分鐘 (0-59)
│ ┌───────────── 小時 (0-23)
│ │ ┌───────────── 日期 (1-31)
│ │ │ ┌───────────── 月份 (1-12)
│ │ │ │ ┌───────────── 星期幾 (0-7,其中 0 和 7 都是星期日)
│ │ │ │ │
* * * * *
就這樣。五個欄位,從左到右:分鐘、小時、日期、月份、星期幾。
你知道嗎? "cron" 這個名稱來自希臘語 "chronos",意為時間。Cron 守護程式(背景程序)自 1975 年以來一直是類 Unix 作業系統的核心部分。
特殊字元
星號(*)— 每個值
星號表示該欄位「每個可能的值」。
* * * * * = 每天每小時的每分鐘。
逗號(,)— 多個值
逗號分隔各個值。
0 9,12,18 * * * = 在第 9、12 和 18 小時的第 0 分鐘(上午 9:00、中午 12:00、下午 6:00)。
破折號(-)— 值的範圍
破折號定義一個範圍。
0 9-17 * * * = 從第 9 到第 17 小時的每個整點(上午 9:00 到下午 5:00,每小時一次)。
斜線(/)— 步進值
斜線定義間隔。
*/15 * * * * = 每 15 分鐘(每小時的第 0、15、30、45 分鐘)。
0 */2 * * * = 每 2 小時的第 0 分鐘(午夜、凌晨 2 點、凌晨 4 點……)。
讀取 Cron 表達式:練習
讓我們逐一解析常見範例。對每個範例,從左到右讀取五個欄位。
0 3 * * * — 每天凌晨 3:00
| 欄位 | 值 | 含義 |
|---|---|---|
| 分鐘 | 0 | 在第 0 分鐘 |
| 小時 | 3 | 在第 3 小時(凌晨 3 點) |
| 日期 | * | 每天 |
| 月份 | * | 每月 |
| 星期幾 | * | 每週每天 |
解讀:「每天凌晨 3:00。」夜間備份的經典選擇。
*/15 * * * * — 每 15 分鐘
| 欄位 | 值 | 含義 |
|---|---|---|
| 分鐘 | */15 | 每 15 分鐘 |
| 小時 | * | 每小時 |
| 日期 | * | 每天 |
| 月份 | * | 每月 |
| 星期幾 | * | 每天 |
解讀:「全天候每 15 分鐘一次。」常用於健康檢查和快取刷新。
0 9 * * 1-5 — 週一至週五上午 9:00
| 欄位 | 值 | 含義 |
|---|---|---|
| 分鐘 | 0 | 在第 0 分鐘 |
| 小時 | 9 | 在第 9 小時 |
| 日期 | * | 每天 |
| 月份 | * | 每月 |
| 星期幾 | 1-5 | 週一至週五 |
解讀:「週一至週五上午 9:00。」非常適合每日工作報告。
0 0 1 * * — 每月第一天
| 欄位 | 值 | 含義 |
|---|---|---|
| 分鐘 | 0 | 在第 0 分鐘 |
| 小時 | 0 | 在第 0 小時(午夜) |
| 日期 | 1 | 在第 1 天 |
| 月份 | * | 每月 |
| 星期幾 | * | 任意星期幾 |
解讀:「每月第一天午夜。」用於月度報告、計費或清理。
30 8 * * 1 — 每週一上午 8:30
| 欄位 | 值 | 含義 |
|---|---|---|
| 分鐘 | 30 | 在第 30 分鐘 |
| 小時 | 8 | 在第 8 小時 |
| 日期 | * | 每天 |
| 月份 | * | 每月 |
| 星期幾 | 1 | 週一 |
解讀:「每週一上午 8:30。」非常適合每週團隊通知。
撰寫你自己的 Cron 表達式
以下是一個系統性的方法:
- 從「何時」開始。 「每天凌晨 3 點」或「工作時間每 5 分鐘」。
- 從左到右填寫欄位。 從分鐘開始,然後是小時、日期、月份,最後是星期幾。
- 「每個」用
*表示。 如果你不關心某個欄位,使用*。 - 部署前先測試。 始終驗證你的表達式產生你期望的排程。
常見規律快速參考
| 排程 | 表達式 |
|---|---|
| 每分鐘 | * * * * * |
| 每 5 分鐘 | */5 * * * * |
| 每小時 | 0 * * * * |
| 每天午夜 | 0 0 * * * |
| 每天凌晨 3:00 | 0 3 * * * |
| 每週一上午 9:00 | 0 9 * * 1 |
| 週一至週五上午 8:30 | 30 8 * * 1-5 |
| 每月第一天 | 0 0 1 * * |
| 工作時間每 15 分鐘 | */15 9-17 * * 1-5 |
| 每天兩次(上午 9 點和下午 6 點) | 0 9,18 * * * |
| 每週日凌晨 2:00 | 0 2 * * 0 |
常見錯誤
忘記小時是 0-23
第 13 小時是下午 1:00,而非第 1 小時。常見錯誤是寫 0 1 * * *,以為它在下午 1:00 執行,但實際上是在凌晨 1:00 執行。
星期幾混淆
星期日可以是 0 或 7(兩者都有效)。星期一是 1,星期六是 6。有些人預期星期一是 0。
日期與星期幾的交互影響
如果你同時指定了日期和星期幾(兩者都不是 *),大多數 cron 實作在任一條件滿足時都會執行任務,而非兩者都滿足時。這讓很多人措手不及。
警告 表達式 0 9 15 * 1 並非表示「在第 15 天的上午 9 點,但只有在週一時才執行」。它的意思是「每月 15 日的上午 9 點,以及每週一的上午 9 點」。這是意外行為的常見來源。
時區意識
Cron 在伺服器的本地時區中運行。如果你的伺服器在 UTC 時區,而你在台北(UTC+8),一個 0 9 * * * 的 cron 任務實際上會在你的時間下午 5 點執行。請始終確認你的伺服器使用的時區。
提示 在部署之前測試和視覺化你的 cron 表達式:如何讀取和測試 Cron 表達式。查看下次執行時間,確認排程符合你的預期。
建立和測試你的 cron 表達式:
免費、即時,無需註冊。