我寫過的最昂貴的克朗表達式是 0 0 * * 0. 它為我正在建造的 Laravel SaaS 運行每週摘要電子郵件,我絕對確定這意味著 "一周最後一天的午夜。&引用;這意味著週日午夜。我的心理模型說這週週六結束了。五週以來,顧客都收到了他們的"評論和引用週;電子郵件遲到了一天,團隊中沒有人抓住它,因為團隊中也沒有人能讀懂 cron - 我們都只是瞇著眼睛看著五個字段點點頭。
那'這是 cron 語法的骯髒秘密:幾乎每個編寫它的人都與他們半記得的先前表達式模式匹配。該格式已有四十多年的歷史,足夠密集,單一字元會完全更改時間表,並且會默默地失敗。那裡' " 沒有編譯器錯誤;在錯誤的日期運行。"這項工作只是在錯誤的一天永遠運行,直到有人注意到。
一個 cron 表達式解析器 縮小這個差距。你貼上表達式,它用簡單的英語告訴你實際會發生什麼 - 0 0 * * 0 返回為 "週日 00:00 " - 另外下次運行何時會觸發。這個回讀步驟是發送時間表和發送猜測之間的區別。我在 toolz。dev 上建立了這個,因為我厭倦了上下文切換到終端,而且因為我在 WP Adminify 中處理了多年的 wp-cron 混亂告訴我,調度錯誤是軟體中最耐心的錯誤。
本指南涵蓋如何使用解析器、五個欄位實際如何運作(包括導致大多數生產事件的兩個怪癖)以及 cron 語法不同的地方 克朗塔布,github 動作、Quartz 和 Laravel。
TL;DR: 將任何 crontab 表達式貼上到 toolz。dev Cron 解析器 並獲得簡單的英文翻譯以及即將到來的運行時間 - 立即、客戶端、無需註冊。在部署時間表之前,請務必驗證兩件事:星期幾編號(0 和 7 均為星期日)和調度程序運行的時區(GitHub 操作始終為 UTC)。將其與配對 時間戳轉換器 當您需要跨區域轉換下次運行時間時,以及 日期差計算器 理智檢查間隔。
主要特點
普通英語翻譯
解析器的核心工作正在轉變 */15 9-17 * * 1-5 進入並引用;週一、週二、週三、週四和週五,過去 9、10、11、12、13、14、15、16 和 17 小時的每 15 分鐘。它'冗長 - 它列舉而不是折疊&引用; 9 到 17&引用;回到一個範圍-冗長是重點。列舉是明確的;總結範圍是另一個誤讀的機會。根據我的經驗,在程式碼審查期間,翻譯最重要:如果評論者會在五個神秘欄位上蓋上橡皮圖章,他會立即捕獲並引用;等等,為什麼當作業應該在下午 5 點停止時,第 17 小時會出現?"當每個小時都拼出來時。翻譯使時間表變得可證偽,而這正是原始 cron 語法失敗的地方。
下次運行預覽
知道什麼是表達 手段 問題有一半;知道什麼時候 接下來開火 是另一半。解析器計算接下來的五個執行時間,這樣你就可以根據自己的意圖觀察它們。這就是微妙錯誤的出現之處 - 這個表達式在英語中讀起來很好,但會產生下一次運行 " 27天&引用;因為你混淆了月中的某一天和月份,或者今晚 03:00 觸發,而你的意思是週末後的 03:00。我現在每次都會檢查下一次運行列表,即使是表達式 I'我對此充滿信心。尤其是表達式 I'我對此充滿信心 - 請參閱開頭軼事。
關於如何計算這些時間的兩個細節。首先,他們'在中評估 您的瀏覽器和#39;當地時區,不是 UTC,也不是您的伺服器' s 區域 - 每次運行顯示兩次,一次作為本地時間戳,一次作為等效 UTC 即時,因此您可以讀取與部署目標相符的內容。其次,當月日和星期兩都受到限制時,解析器應用真實的 cron's 或語義而不是 AND: 0 0 1 * 1 本月 1 日發生火災 和 每個星期一,而不僅僅是第一個星期一。這條規則讓有經驗的人感到困惑,看到五個具體日期,這句話從未如此明顯。
一個粗略的邊緣:一種不可能的表達方式 0 0 30 2 * (2 月 30 日)解析為有效,愉快地將自己描述為 " 2 月第 30 天的 00:00,"然後顯示一個空的下一次運行清單。空意味著永遠不會。它'正確,但它'安靜-a"這個時間表永遠不會觸發"警告是明顯的改進,我還沒有'還沒有建造它。
臨時故障
解析器將表達式分為五個組成部分 - 分鐘、小時、月中的日、月中的日、星期中的日 - 並顯示每個組成部分的貢獻。這很重要,因為 cron 錯誤幾乎總是一個單場問題:錯誤列中的正確值。 0 12 * * * (每天中午)和 12 0 * * * (每天中午 12:12...不,每天 00:12)相隔一交換。查看並引用;小時:0&引用;明確標記的是如何在兩秒而不是兩週內完成交換。
支援範圍、步驟和清單
現實世界的表達式嚴重依賴運算子語法: 1-5 範圍, */10 步驟, 1,15 列表和組合,例如 0 8-18/2 * * 1,3,5。 解析器處理所有這些,包括絆倒人類讀者的組合形式。範圍內的步值 - 8-18/2 意義&引用;從 8 到 18 每 2 小時一次&引用; - 合法、有用,如果沒有工具幾乎無法讀取。如果您'您曾經從已離職的系統管理員那裡繼承過裝滿這些內容的 crontab,您就知道為什麼存在此功能。
嚴格的五場驗證(包括它贏得什麼和#39;t 接受)
解析器採用標準的五域表達式,僅此而已。貼上 @daily 你會得到一個錯誤 - "預期的 5 個欄位(分鐘小時、月日、月日、週日),得到 1" - 不是翻譯。相同 @hourly, @weekly, 和 @reboot. That'這是一個真正的差距,而不是一個設計原則,而 I'寧願這麼說,也不願讓你在調試中找出答案;速記巨集在真實的 crontab 中非常常見,因此它們屬於該工具。直到他們'重新輸入,手動翻譯: @hourly 是 0 * * * *, @daily 是 0 0 * * *, @weekly 是 0 0 * * 0, @monthly 是 0 0 1 * *, @yearly 是 0 0 1 1 *. @reboot 根本沒有相當於五個字段的 - 它是 't 一個時間表,它在守護程式啟動時運行一次,這一事實讓許多從 crontab 運行遷移的人感到驚訝。
嚴格性在其他地方得到了回報。六場石英表達式被拒絕,並帶有場計數,而不是默默地誤讀。超出範圍的值命名欄位和法律範圍 (Value 25 out of range for hour (allowed 0-23)).反轉範圍如 5-1 被抓住了。它接受真實 crontabs 包含的內容:月份和日期名稱 (()JAN, SUN), 7 作為 Sunday 和 Vixie 的第二個拼寫 5/15 形成意義&引用;從 5 開始的每 15 個;。值得在您時了解'手動翻譯這些巨集:每一個 @daily 伺服器上的作業會在同一時刻(午夜)觸發,因此其中 40 個是夜間負載峰值。我把我的分散在奇怪的分鐘內()17 3 * * *, 43 4 * * *) 正是出於這個原因。
客戶端處理
解析器完全在您的瀏覽器中運行。您貼上的任何內容都不會上傳、記錄或儲存。這聽起來像是樣板隱私語言,直到您記住 crontabs 實際包含的內容:您的備份計劃、計費運行時間、安全掃描觸發的確切時間。基礎設施調度是偵察資料。遠離其他人'伺服器是'偏執狂;它'只是不會造成不需要存在的問題。
如何使用 Cron 解析器
第 1 步:貼上或輸入您的表達式
打開 克朗解析器 並刪除表達式 - 來自 crontab 文件,a schedule: github Actions 工作流程、Kubernetes CronJob 清單或 Laravel 中的區塊 ->cron() 呼叫。標準五字段語法按原樣工作; @daily 它的兄弟姊妹 don't,所以先將這些欄位展開到五個欄位。然後點擊解析。如果你'從頭開始而不是解碼,預設按鈕(每分鐘、每小時、每天午夜、工作日上午 9 點、每月 1 日)載入一個工作表達式,您可以逐場修改,邊走邊重新解析。
第 2 步:閱讀翻譯
這是人們跳過並且應該做的步驟't。閱讀純英語輸出並將其與腦中的句子進行比較。如果您寫了"意圖&引用"這一表達方式;每週一上午 9 點&引用;回讀內容顯示 "第 1 個月的 09:00; - 恭喜您,您剛剛在生產之前捕獲了經典的列交換。回讀是您的單元測試。
第三步:驗證下一次運行時間
檢查即將執行的五次處決。日期會落在您預期的位置嗎?是今晚、明天或下個月的第一次運行嗎?注意運行之間的間隙 - 一個錯誤的位置 */ 步轉&報價;每 6 小時&報價;進入&報價;每 6 小時每分鐘&報價; (* */6 * * * vs 0 */6 * * *),五跑一分鐘而不是六小時是很難錯過的。空清單意味著時間表永遠不會啟動。
步驟 4:部署前考慮時區
解析器告訴你 當 相對於時鐘;您的調度程序決定 誰的 時鐘。部署前,確認執行系統使用什麼時區。 GitHub 動作:始終為 UTC,無一例外。伺服器:無論作業系統設定為什麼,雲端盒上經常為 UTC。 Laravel:您的應用程式時區,除非您連結 ->timezone(). 翻譯下一次運行時間 時間戳轉換器 如果您需要在當地區域或客戶處查看它's。
技術深度潛水:Cron 表達式實際工作原理
五字段格式來自 Unix cron,由 Paul Vixie 和#39 在實踐中標準化; 20 世紀 80 年代末的 cron 實作 - 記錄於 crontab(5) 如今,它仍然以後代形式在大多數 Linux 系統上發貨。字段,從左到右:
| 田野 | 允許的值 | 筆記 |
|---|---|---|
| 分鐘 | 0.59 | |
| 小時 | 0 第23章 | 24小時制,0點為午夜 |
| 月中的一天 | 1.31 | 小心沒有 31 號的幾個月 |
| 月 | 1 點 12 分或一月 12 日 | Vixie cron 中允許使用名稱 |
| 一周中的一天 | 0 點 7 分或太陽點衛星 | 0和7都是星期日 |
每個欄位接受 * (任何值),列表(1,15),範圍(1-5),以及步驟(*/10 或者 20-59/5).那'是整個語法。語法中的複雜度是't - it'三個行為怪癖。
怪癖一:一周中的零日。 每 crontab(5)0 和 7 都表示週日。一些較舊或更嚴格的實作只接受 0。 Quartz - Jenkins 和一半企業軟體使用的 Java 調度程序 - 從第 1 天到第 7 天開始編號 週日所以石英's 2 是星期一,crontab's 2 是星期二。如果您曾經在系統之間遷移時間表,那麼這個斷斷續續的安排正在等待。始終解析,切勿轉錄。
怪癖二:月日或週日。 這裡'是幾乎沒有人知道的人,直到它咬了他們。什麼時候 兩者 月中的日和周中的日欄位受到限制(兩者都沒有) *),Vixie cron 負責這項工作 要么 匹配 - 一個 OR,而不是一個 AND。所以 0 0 13 * 5 不't 均值&引用; 13號星期五。&引用;它的意思是&引用;每月 13 日和每週五。&引用;這是記錄在案的行為 crontab(5) 這是非常違反直覺的。如果您確實需要 " 13 號星期五,"您需要腳本端日期檢查或語法更豐富的調度程序。
怪癖三:時區和夏令時。 Cron 沒有時區欄位。該表達式在調度程序's 當地時間中進行解釋,無論是什麼。兩個具體後果:
- GitHub 動作正在運行
schedule:UTC 中的觸發器,句號。 工作流程安排在0 9 * * *紐約的火災時間為世界標準時間上午 9 點 - 上午 4 點或 5 點,具體取決於季節,因為世界標準時間不觀察夏令時,但您的目標受眾和#39;時鐘會觀察夏令時。你的&報價;上午 9 點 每日報告&報價;每年兩次漂移一小時,除非您調整工作流程或以程式碼處理。 - 在設定為 DST 觀察區的伺服器上,每年一晚 02:00 °C03:00 不存在 #39;不存在,一晚發生兩次。 02:30 預定的作業會根據實施情況跳過或雙重觸發。無聊、正確的修復:在本地 01:00 到 03:00 之外安排關鍵作業,或在 UTC 上運行伺服器。我兩者都做。
擴展格式。 Quartz 使用六個或七個欄位(領先秒數欄位和可選的尾隨年份),以及額外的運算符,例如 L (最後), W (最近的工作日),以及 # (每月的第n個工作日)。有些 cron 也支援領先秒數欄位。如果您的表達式有六個字段,並且 you'不確定它是哪種方言,請將其貼到解析器中 - 解釋為五字段的六字段表達式將產生明顯錯誤的輸出,這本身就是診斷性的。和 @reboot39;t 是一個時間表,它根本就是一個時間表:它在守護程序啟動時運行一次,這在現代系統上意味著 "每當盒子重新啟動時,"這一事實讓許多從 crontab 運行資料庫遷移的人感到驚訝。
為了更廣泛地了解與調度工作相結合的開發人員實用程序, 編碼工具指南 覆蓋整個工具箱。
常見用例
調試 Laravel 調度程式條目
Laravel's 調度程序以流暢的方法包裝 cron - ->dailyAt('03:00'), ->weeklyOn(1, '8:00')- 但逃生艙口, ->cron('*/5 * * * 1-5'), 是原始的 crontab 語法,複雜的時間表最終會在那裡。系統 crontab 運行 schedule:run 每分鐘,拉拉維爾都會在內部決定什麼's到期。當預定的命令是't射擊時,我的第一步是貼上 ->cron() 字串到解析器中以確認它意味著上面評論所聲稱的含義。大約一半的時間,它沒有't。另一半,錯誤是時區:應用程式設定為 UTC 而開發人員則假設當地時間。解析器在幾秒鐘內解決第一個情況,並將手指指向第二個情況。
在 WordPress 網站上解開 wp-cron
WordPress 附帶 wp-cron,它是 't cron all - it'是一個偽調度程序,可以隨身攜帶頁面訪問,因此是一個低流量網站's&報價;每小時&報價;作業可能每四個小時運行一次,高流量網站會為每個請求繳納少量稅。在我的 WP 管理期間,這產生了源源不絕的 "預定貼文 aren't 發布&報價;報告。標準修復是停用 wp-cron (DISABLE_WP_CRON) 並觸發 wp-cron.php 從真實的伺服器 crontab - 此時您'通常正在編寫實際的 cron 表達式 */5 * * * *,解析器可以不斷驗證它們。如果您以任何規模運行 WordPress,那麼這種遷移值得本週進行,而不是有一天。
驗證 GitHub 操作時間表
CI 時間表悄悄失敗:停止運行的夜間構建不會'不會給任何人尋呼。寫a時 schedule: 觸發,我解析表達式,查看下一次運行時間,然後在心裡添加 UTC 偏移量。特定於操作的兩個額外細節:時間表僅在預設分支上運行,並且在高負載期間可以延遲或刪除運行 - GitHub'自己的文檔這麼說。如果確切的時間很重要,則 cron 觸發的操作是錯誤的工具;如果近似計時很好,至少將近似時間設為 正確的 大約時間。
審計繼承的 Crontab
每個長壽命的伺服器都會累積一個由不再在那裡工作的人編寫的 crontab。跑步 crontab -l 透過解析器貼上每一行是我所知道的最快的審核:十分鐘內,您就會得到一份簡單的英語時間表清單,並且您幾乎總是會發現至少一項工作正在做一些沒人記得的事情- 備份運行兩次,清理腳本永遠不會匹配它應該匹配的日期,a * * * * * 那應該是 0 * * * * 每小時敲擊 API 六十次。當在遷移過程中將舊的 crontab 與新的 crontab 進行比較時, 文字差異工具 除了解析器之外,審查也變得機械化。
安排 Kubernetes CronJobs
K8 的 CronJobs 使用標準的五字段語法,並且從 1.27 開始支援明確語法 timeZone 字段 - 對經典 cron 的真正改進。解析器工作流程相同:驗證表達式,檢查下一次運行,然後確認 startingDeadlineSeconds 和 concurrencyPolicy 覆蓋失敗模式 cron 本身不't。表達式可以是完美的,如果緩慢運行與下一個觸發器重疊,作業仍然會堆積;解析器可以正確安排時間表,以便您可以將注意力集中在這些操作設定上。
克朗方言比較
| 潑婦克朗/克朗塔布 | GitHub 操作 | 石英 | 拉拉維爾調度程序 | 系統計時器 | |
|---|---|---|---|---|---|
| 領域 | 5 | 5 | 6 FOR7(秒,年) | 5(通過 ->cron()) |
OnCalendar 語法,不是 cron |
| 每週編號 | 0 ATV7(0 和 7 = 太陽) | 0 點 6 分(0 點 = 太陽) | 1 分 7 秒(1 = 太陽) | 跟隨克朗塔布 | 姓名 (Mon, Tue) |
| 時區 | 系統本地 | 始終為世界標準時間 | 可配置的 | 應用程式時區或 ->timezone() |
系統本地或 Timezone= |
| 特殊字串 | @daily, @reboot等等。 |
不支援 | 不支援 | 相反,方法是流暢的 | OnBootSec=,日曆簡寫 |
| 秒精度 | 不 | 不(至少 ~5 分鐘實用) | 是的 | 否(每分鐘勾選) | 是的 |
| 最好 | 伺服器作業 | CI/CD 時間表 | JVM 生態系 | 拉拉維爾應用程式 | 現代 Linux 服務 |
何時使用:crontab 用於普通伺服器作業,systemd 定時器(當您希望在現代Linux 上免費記錄和依賴關係處理時),框架調度器(當作業無論如何都存在於您的應用程式內時),以及僅針對容忍模糊定時的CI 任務的操作調度。無論您選擇哪一個,五字段表達式都是通用語言 - 這就是為什麼流利地說它的解析器屬於您的書籤,旁邊是您的其他內容 web 開發人員工具包.
問號
什麼是 cron 表達式解析器?
cron 表達式解析器是一種讀取 crontab 語法的工具 */15 9-17 * * 1-5- 並將其翻譯成簡單的英語時間表描述,通常與下一個執行時間的預覽一起。它允許您在部署計劃之前驗證計劃的實際用途,而不是在作業在生產中的錯誤時間觸發時發現誤讀欄位。
cron 表達式中的五個欄位是什麼意思?
由左至右:分鐘(0 0 59)、小時(0 0 23)、月日(1 0 31)、月(1 0 12)和星期一(0 0 7,其中 0 和 7 均表示星期日)。每個欄位接受 * 對於任何值,逗號列表、連字符範圍和 / 步值。所以 30 2 1 * * 指每月第一天的 02:30。
為什麼我的cron工作在錯誤的時間進行?
兩個最常見的原因是時區和欄位混亂。 Cron 在調度程序' 中運行;本地時間 - GitHub Actions 始終使用 UTC,許多雲端伺服器也這樣做 - 因此為 " 安排作業;9 AM"可能會從掛鐘中關閉幾個小時。另一個經典是交換字段,例如將小時值放入分鐘列中。解析表達式並檢查下一次運行時間可以捕獲兩者。
0 和 7 都是主日的 cron 嗎?
在 Vixie cron 和大多數 Linux 實作中,是的 - crontab(5) 手冊頁允許週日使用 0 和 7。但這並不普遍:石英數字第1 天到第7 天從週日開始,一些嚴格的解析器拒絕7。 在系統之間移動表達式時,重新驗證星期幾字段,而不是假設編號延續。
什麼 0 0 13 * 5 真的嗎?
不是&報價; 13號星期五。&報價;當月日和週日都受到限制時,標準 cron 將它們視為 OR:該作業每月 13 日運行 和 每個星期五。這是記錄的 Vixie cron 行為,也是格式之一'最容易被誤解的規則。如果您需要真正的 AND,請在腳本本身內新增日期檢查。
夏令時如何影響 cron 工作?
在 DST 觀察時區的伺服器上,安排在當地時間 01:00 至 03:00 之間的作業可以跳過運行(當時鐘向前跳轉時)或運行兩次(當它們向後跳轉時),具體取決於實現情況。最安全的模式是在 UTC 上運行伺服器或在該視窗之外調度關鍵作業。請注意,基於 UTC 的調度程序(例如 GitHub Actions don't)會跳過運行,但它們對應的本地時間每年兩次輪班一小時。
是 @daily 相同 0 0 * * *?
是的 - @daily (及其同義詞 @midnight) 精確地擴展到 0 0 * * * 在 Vixie cron 中。兩個警告。首先,toolz。dev 解析器只接受五域表達式,因此貼上 0 0 * * * 而不是 @daily 現在。第二,每一個 @daily 作業在同一時刻觸發,因此擁有許多作業的伺服器會遇到午夜負載峰值。將日常工作分散在交錯的分鐘和小時中,可以避免自殘的雷鳴群。
toolz。dev cron 解析器上傳我的表達式嗎?
不 克朗解析器 完全在瀏覽器中運行 - 表達式在客戶端解析,永遠不會發送到伺服器、記錄或儲存。由於 crontab 會洩露備份時序和計費運行等操作詳細信息,因此將它們排除在第三方伺服器之外是明智的預設操作,您可以自行在瀏覽器中確認該行為's 網路標籤。
裝運前請先閱讀
五週的摘要電子郵件遲到一天並不是一個戲劇性的中斷。沒有人給我發頁。那'這正是導致日程安排錯誤昂貴的原因:他們不知道並#39;不宣布自己,他們只是悄悄地做錯事,直到顧客順便提到它。為我修復它的習慣是'紀律或更好地記憶現場訂單 - it'三十秒的回讀。貼上表達式,閱讀英文句子,查看五個具體日期,然後部署。
保留 克朗解析器 在工具旁邊,你'將在同一調試會話中觸及: 時間戳轉換器 當下一次運行時間需要在區域之間移動時(I'已經寫好了) Unix 時間戳陷阱 那咬得最難), 日期差計算器 用於健全性檢查間隔,以及 文字差異工具 當你'在遷移過程中將舊的 crontab 與新的 crontab 進行比較。這 編碼工具指南 瀏覽一下該集如何組合在一起,並且所有內容都在客戶端運行 - 對於在備份和計費觸發時準確記錄的文件來說,這是唯一合理的預設值。



