什麼是 Cron 運算式?
Cron 運算式是一個精簡的排程字串,用來告訴排程器確切的任務觸發時間。此格式誕生於 1975 年 Unix V7 的 cron 守護程序,幾乎從未改變——相同的五欄位語法如今仍出現在 Kubernetes CronJob、AWS EventBridge、GitHub Actions 工作流程、Google Cloud Scheduler、GitLab CI、Jenkins 流水線,以及所有 Linux 發行版隨附的 crontab 二進位程式中。十三個左右的字元承載了大量含義,這正是能將其轉換為易讀英文的解析器之所以重要的原因——它是自信部署與凌晨三點回滾之間的差距。
Cron 運算式如何運作?
標準的 Cron 運算式包含五個以空格分隔的欄位,共同定義一個重複排程。排程引擎每分鐘將當前時鐘與運算式進行比對,當五個欄位全部符合時觸發任務。從左到右各欄位為:
- 分鐘(0–59)。任務在小時內的哪一分鐘執行。
0表示整點,30表示半點,*/5表示每五分鐘(00、05、10……),15,45表示 15 分和 45 分。 - 小時(0–23)。以 24 小時制表示一天中的哪個小時。
0為午夜,9為上午 9 點,17為下午 5 點。範圍(9-17表示工作時間)和步進值(*/2表示每隔一小時)的用法與分鐘欄位相同。 - 月份中的日(1–31)。在哪個日曆日執行。
1表示每月 1 日,*表示每天,1,15表示 1 日和 15 日。注意31會靜默跳過沒有 31 日的月份。 - 月份(1–12 或 JAN–DEC)。在哪些月份執行。
*表示每個月,1,7表示一月和七月,1-3表示第一季。三字母月份名稱在多數實作中不區分大小寫。 - 星期幾(0–7,其中 0 和 7 均表示週日)。限制在特定工作日觸發。
1-5表示週一到週五,0,6表示週末,MON-FRI在多數解析器中有效。當月份日和星期幾都設為具體值時,傳統 cron 會在任一條件符合時觸發(邏輯 OR),這幾乎每次都令人意外。
為什麼使用 Cron 運算式解析器?
- 在部署前發現靜默的誤讀。運算式 `0 2 */3 * *` 表示每隔三天凌晨 2 點執行,而非每三分鐘——貼上來即可用中文確認,不必等到部署後才發現。
- 多數雲端排程器預設使用 UTC。以本地時區預覽下 10 次執行時間,可在凌晨 3 點被呼叫之前發現日光節約時間偏差。
- `@daily`、`@weekly` 和 `@monthly` 等快捷方式方便但模糊。解析器會顯示底層的五欄位格式,讓您確切了解排程內容。
- 逐欄位建立器讓您每次設定一個欄位,並即時看到人類可讀描述更新,比第十次重讀 cron 手冊頁快得多。
Cron 運算式的使用場景
只要需要按時鐘重複執行任務,就會出現 Cron 語法。以下是三個最常見的平台及其各自的注意事項:
- 備份排程。經典的 `crontab -e` 條目,在每晚凌晨 2 點將資料庫匯出到 S3,或在每月 1 日輪替 `pg_dump` 封存。像 `0 2 * * * /usr/local/bin/backup.sh` 這樣的一行程式碼,比任何其他 cron 排程都被部署在更多 Linux 伺服器上。把分鐘和小時設對,把 stderr 重導向到持久存放,就可以用自動化取代人工清單。
- GitHub Actions `schedule` 觸發器。`.github/workflows/*.yml` 中的 `on.schedule.cron` 鍵接受標準五欄位 cron,但任務始終在 UTC 執行,且如果執行器佇列繁忙,GitHub 會靜默跳過某次執行時間。常見模式:`cron: '0 9 * * 1-5'` 在每週一到週五 UTC 上午 9 點發送摘要。先在本地時區預覽,避免承諾上午 9 點的摘要卻在 BST 的上午 10 點才送達。
- AWS EventBridge Scheduler。EventBridge cron 運算式需要年份作為第六個欄位,並且要求在月份日或星期幾欄位中使用 `?` 而非 `*`——`cron(0 9 ? * MON-FRI *)` 是標準工作日上午 9 點 cron 的 EventBridge 翻譯。用於排程 Lambda 呼叫、ECS 任務執行和 Step Function 狀態機啟動;與標準 cron 語法的不一致是 CloudFormation 部署中 `ValidationException` 錯誤的頭號來源。
真實的 Cron 運算式長什麼樣?
以 0 9 * * 1-5 為例——在每個工作日上午 9 點觸發。從左到右讀取各欄位:0 是小時的第零分鐘,9 是 24 小時制的上午 9 點,月份日的 * 表示每個日曆日,月份的 * 表示每個月,星期幾的 1-5 將觸發限制為週一到週五(標準 cron 編號中 1 = 週一)。將其貼入上方輸入框,解析器會在您選擇的 IANA 時區中確認每週一到週五上午 09:00,並顯示下 10 次執行日期。同樣意圖的 AWS EventBridge 語法為 cron(0 9 ? * MON-FRI *)——注意末尾的年份欄位和標準 cron 使用 * 的地方改為 ?。三個不同的平台,三種不同的表示形式,但底層是相同的排程。
Cron 運算式只有一種方式是不容錯的:一個拼寫錯誤就能產生語法正確但時間錯誤的排程,且在程式碼審查中沒有任何錯誤可以捕獲。讀取 `0 0 1 * *` 並知道它在每月 1 日午夜執行,而非 1 月 1 日,是需要練習的。上方的解析器將這種練習轉化為十秒鐘的健全性檢查——貼上運算式,閱讀中文說明,掃描本地時區的下 10 次執行時間,然後滿懷信心地提交 YAML,確信 cron 行確實執行了提交訊息所說的事情。
五欄位和六欄位 cron 有什麼區別?
五欄位 cron 是精確度為分鐘的傳統 Unix 語法。六欄位 cron 增加了一個前置的秒欄位,用於次分鐘排程——Quartz 和 Spring 的 @Scheduled 使用此格式。AWS EventBridge 也使用六個欄位,但其額外欄位是末尾的年份,而非秒。
@hourly、@daily 和 @weekly 是什麼意思?
這是 1987 年 Vixie-cron 引入的暱稱。@hourly = 0 * * * *,@daily = 0 0 * * *,@weekly = 0 0 * * 0,@monthly = 0 0 1 * *,@yearly = 0 0 1 1 *。@reboot 在啟動時執行一次。GitHub Actions 和 EventBridge 不支援這些別名。
cron 中週日是第 0 天還是第 7 天?
在傳統 Vixie cron 中兩者皆可——0 和 7 均被接受,使 5-7 這樣的範圍可以自然地讀作週五到週日。週一始終是 1,週六始終是 6。Quartz 和 AWS EventBridge 使用不同的慣例:1-7,週日為 1。使用前請查閱平台文件。
cron 如何處理日光節約時間?
取決於引擎的時區。在 UTC(EventBridge、Kubernetes 和 GitHub Actions 的預設值)中不存在日光節約時間。在本地 DST 時區中,傳統 Vixie cron 在春季撥快的空窗期跳過任務,在秋季撥慢時執行兩次;systemd 計時器則只觸發一次。