cron 是類 Unix 系統排定重複性工作的方式,它的表達式格式遠不只用在 crontab——CI 流程、Kubernetes CronJob、各種雲端排程都用它。語法乍看很神祕,其實就是用空白隔開的五個欄位。
五個欄位
┌── 分 (0–59)
│ ┌── 時 (0–23)
│ │ ┌── 日 (1–31)
│ │ │ ┌── 月 (1–12)
│ │ │ │ ┌── 星期 (0–7,0 與 7 都是星期日)
│ │ │ │ │
* * * * *
每個欄位回答「在哪些值執行?」* 代表「每一個」。所以 * * * * * 是每一分鐘都執行。
欄位內的語法
*——每一個值。5——剛好是 5。1-5——範圍,1 到 5。*/15——間隔:每 15 個(0、15、30、45)。1,15,30——特定值的清單。- 名稱——月份用
JAN–DEC,星期用SUN–SAT。
可直接套用的範例
| 表達式 | 意思 |
|---|---|
* * * * * | 每分鐘 |
*/5 * * * * | 每 5 分鐘 |
0 * * * * | 每小時整點 |
0 9 * * * | 每天 09:00 |
0 9 * * 1-5 | 週一至週五 09:00 |
0 0 * * 0 | 每週日午夜 |
0 0 1 * * | 每月 1 號 |
30 3 1 1 * | 1 月 1 日 03:30 |
唯一的陷阱:日 vs 星期
如果「日」和「星期」兩個欄位都有限定(不是 *),cron 會在任一符合時執行——不是兩個都要符合。所以 0 0 13 * 5 會在每月 13 號以及每個星期五執行,而不是只在「13 號星期五」。不確定時,就用實際執行時間來驗證。
上線前先驗證
最保險的做法,是先看它「實際會在哪些時間點觸發」。Cron 表達式產生器會用白話說明每個欄位,並列出你本機時區的下次執行時間,還有一鍵範本。全程在你的瀏覽器本機執行。
相關工具
- 也在處理 Unix 時間戳?用時間戳轉換工具。
快捷字串
多數 cron 服務都接受用具名快捷字串取代那五個欄位:
| 快捷字串 | 等同於 | 何時執行 |
|---|---|---|
@yearly(或 @annually) | 0 0 1 1 * | 每年一次,1 月 1 日 |
@monthly | 0 0 1 * * | 每月 1 號 |
@weekly | 0 0 * * 0 | 每週日 |
@daily(或 @midnight) | 0 0 * * * | 每天午夜 |
@hourly | 0 * * * * | 每小時 |
@reboot | —— | 開機時一次 |
也要留意欄位數量的差異:Spring 的 @Scheduled、Quartz,以及部分雲端排程會在最前面多一個秒欄位(共六欄);AWS EventBridge 則用六欄格式,且禁止同時指定「日」與「星期」。把五欄表達式貼進六欄的解析器,整串就會錯開一欄。
時區與日光節約時間
傳統 crontab 沒有時區欄位——它是以服務所在機器的本地時間觸發。在 Linux 上,你可以在檔案裡加一行 CRON_TZ=UTC(或 TZ)來覆寫;多數雲端排程則是提供一個時區下拉選單。凡是跨區域共用的排程,用 UTC 最保險,誰都不必再心算時差。
日光節約時間的切換是經典陷阱。時鐘往前撥時,落在被跳過那一小時內的工作(例如 30 2 * * *)當天可能不會執行;往回撥時,落在重複那一小時的工作則可能跑兩次。把重要工作排在 01:00–03:00 之外,或直接用 UTC。如果你同時也在處理 epoch 時間,Unix 時間戳完整教學說明了它們怎麼對應到牆上時鐘的時間。
快速 FAQ
- 範圍和間隔能一起用嗎? 可以——
0-30/10代表 0、10、20、30。 - 「時」欄位裡的
*/2是什麼意思? 每隔一小時:0、2、4⋯22。 - cron 會補跑錯過的排程嗎? 不會。若排定時間點機器是關的,單純的 cron 就直接略過——需要補跑請用
anacron。