跳到主要內容

← 返回部落格

Cron 表達式完整解讀:五個欄位與常用範例

cron 是類 Unix 系統排定重複性工作的方式,它的表達式格式遠不只用在 crontab——CI 流程、Kubernetes CronJob、各種雲端排程都用它。語法乍看很神祕,其實就是用空白隔開的五個欄位。

最常見的那個排程,我們的工具怎麼讀它。 在 cron 產生器輸入 0 9 * * 1-5,它會把每個欄位念回來:

Minute: 0
Hour: 9
Day of month: every
Month: every
Day of week: Mon-Fri

這裡看得到兩個最常讓人踩坑的地方。「日」與「星期」都是 every,而當兩者都不設限時,排程就是每天跑 —— 但如果兩個都設了限制,它們的行為是 OR 而不是 AND,那是 cron 最常見的 bug。另外 1-5 是週一到週五,因為一週從 0 = 星期日開始算。

五個欄位

┌── 分 (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

下面每一條「人話」都是我們自己的 cron 產生器吐出來的 —— 它把五個欄位解析出來再用文字唸回去,這是抓「欄位數錯位」最快的方法。

運算式我們的工具讀成
* * * * *分: 每個 時: 每個 日: 每個 月: 每個 星期: 每個
*/15 * * * *分: 每 15 個 時: 每個 日: 每個 月: 每個 星期: 每個
0 * * * *分: 0 時: 每個 日: 每個 月: 每個 星期: 每個
0 9 * * 1-5分: 0 時: 9 日: 每個 月: 每個 星期: 一-五
30 3 * * 0分: 30 時: 3 日: 每個 月: 每個 星期: 日
0 0 1 * *分: 0 時: 0 日: 1 月: 每個 星期: 每個
0 0 * * 1分: 0 時: 0 日: 每個 月: 每個 星期: 一
0 */2 * * *分: 0 時: 每 2 個 日: 每個 月: 每個 星期: 每個

唯一的陷阱:日 vs 星期

如果「日」和「星期」兩個欄位都有限定(不是 *),cron 會在任一符合時執行——不是兩個都要符合。所以 0 0 13 * 5 會在每月 13 號以及每個星期五執行,而不是只在「13 號星期五」。不確定時,就用實際執行時間來驗證。

最容易讓人絆倒的兩條運算式只差一個字元。0 0 1 * * 讀成 分: 0 時: 0 日: 1 月: 每個 星期: 每個 —— 每個月的第一天。0 0 * * 1 讀成 分: 0 時: 0 日: 每個 月: 每個 星期: 一 —— 每個星期一。第 3 欄是「日」、第 5 欄是「星期」;在多數實作裡兩個同時設定是 OR 而不是 AND,所以 0 0 1 * 1 會在每月 1 號以及每個星期一都跑。

上線前先驗證

最保險的做法,是先看它「實際會在哪些時間點觸發」。Cron 表達式產生器會用白話說明每個欄位,並列出你本機時區的下次執行時間,還有一鍵範本。全程在你的瀏覽器本機執行。

相關工具

快捷字串

多數 cron 服務都接受用具名快捷字串取代那五個欄位:

快捷字串等同於何時執行
@yearly(或 @annually)0 0 1 1 *每年一次,1 月 1 日
@monthly0 0 1 * *每月 1 號
@weekly0 0 * * 0每週日
@daily(或 @midnight)0 0 * * *每天午夜
@hourly0 * * * *每小時
@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。