驚きを起こさない Cron 式の書き方
5 つのフィールドとその範囲、名前と数字、日・曜日フィールドの OR トラップ、日曜は 0 か 7 か、夏時間のギャップと重複、そしてデプロイ前に次回実行プレビューで検証する方法。
5 フィールドを左から右へ読む
古典的な cron 式はスペース区切りの 5 フィールドです。分(0–59)、時(0–23)、日(1–31)、月(1–12)、曜日(0–7)。各フィールドは単一の値、カンマ区切りのリスト、ハイフンの範囲、スラッシュ後のステップ、またはすべての値を意味するアスタリスクを受け付けます。
cron のバグの大半は珍しい構文ではなく、普通のフィールドの読み違いです。範囲の境界でリセットされるステップや、23 まで数える系で 12 時間制のつもりで書かれた時フィールドなどです。
- リストリストは離散的な値を選びます。分フィールドの 0,30 は毎時 0 分と 30 分に発火します。
- 範囲とステップ範囲はスパンを選びます。時フィールドの 9-17 は就業時間をカバーし、ステップはそれを間引きます。9-17/2 はスパン内で 2 時間おきに発火します。
- アスタリスクは全マッチアスタリスクは「このフィールドを無視」ではありません。すべての値に能動的にマッチし、2 つの日付フィールドが相互作用した瞬間に重要になります。
名前はドキュメント付きの数字
月と曜日フィールドは、数字のエイリアスとして 3 文字の英語名——JAN から DEC、SUN から SAT——を受け付けます。0 9 * JAN MON と 0 9 * 1 1 は同じスケジュールですが、名前版は次の読者に自己説明し、オフバイワンの編集にも耐えます。
- 大文字小文字を区別しない名前のパースは大文字小文字を区別しません。mon、Mon、MON はすべて通りますが、意図的に見える慣例は大文字です。
- 範囲内の名前名前は範囲やリストの中でも使えます。MON-FRI が標準的な平日スパンで、JAN,APR,JUL,OCT は四半期の月を選びます。
- 説明を読むCron 作成・説明ツールは式を正規化し、フィールドごとに説明します。「month: every value」「weekday: 1, 2, 3, 4, 5」のように、パーサーが名前を意図どおり読んだか確認できます。
日と曜日の二つのフィールドの関係
このツールは Vixie 型の日付規則に従います。日と曜日のどちらも * で始まらない場合、片方の一致で発火します。0 9 13 * FRI は「13 日の金曜日」ではなく、毎月 13 日と毎週金曜日を意味します。
説明ツールの出力はこの点を明示します。意味論を dom-dow-or として計算済みの実行と並べて報告するため、意図よりはるかに頻繁に発火する式は crontab に入る前に正体を現します。
- ワイルドカードのステップにも制約がある日または曜日のフィールドが */2 のようなステップを含め * で始まる場合、このツールは両方のフィールドの一致を求めます。ステップの制約も残ります。
- 先頭に * がなければ ORどちらの日付フィールドも * で始まらない場合、このツールは OR として扱い、日または曜日の一致で発火します。
- AND には工夫が必要本物の「13 日の金曜日」を狙うには、cron に 13 日を選ばせ、コマンド自身に曜日を確認させるか、AND 意味論を持つスケジューラを使います。古典的 cron は後者ではありません。
日曜は 0、たいてい 7 でもある
曜日フィールドは日曜を 0、月曜を 1、土曜を 6 と数えます。多くの実装は月曜から数える人のために 7 も 2 つ目の日曜として受け付けます。Toolars のパーサーは内部的に 7 を 0 に正規化します。ただし片方しか受け付けない系もあり、月曜を 1 とする ISO 式の番号付けも別の場所には存在します。
- 0 と 77 が受け付けられる場所では 0 と 7 はどちらも日曜です。0 と書くのがスケジューラ間で移植性のある選択です。
- 静かなオフバイワン7 を拒否する系で曜日に 7 と書けばデプロイ時に明示的に失敗しますが、「月曜から数えて 7 日目」と読み違えると、間違った曜日に静かに失敗します。
- プラットフォームごとに再確認式が実装間を移るとき——システムの crontab、コンテナ基盤、CI スケジューラ——番号付けが無事に旅を終えたと想定せず、曜日の番号を再確認してください。
夏時間はスケジュールを歪める
夏時間の切り替えでは、存在しない分や繰り返される分が生じます。このプレビューは春の欠落区間にある 02:30 を飛ばし、秋に重なる一致時刻を 2 回表示します。実際のスケジューラは補填実行や重複抑制を行う場合があるため、独自の規則を確かめてください。
- 消える 1 時間春の欠落区間:プレビューに一致する 02:30 はありません。一部のスケジューラは切り替え後に未実行分を補います。
- 倍になる 1 時間秋の重複区間:プレビューは両方の一致時刻を表示できますが、実際のスケジューラは 2 回目を抑制する場合があります。
- UTC に夏時間はないきれいな逃げ道は UTC です。夏時間の切り替えがないため、30 2 * * * は一年中どの日も同じ瞬間を意味します。説明ツールは UTC、デバイスのローカルゾーン、America/New_York や Europe/London などの名前付きゾーンを提供します。
希望的観測ではなく次回実行で検証する
正しい式とそれらしく見える式の違いは、具体的な発火時刻のリストです。Cron 作成・説明ツールは選択したタイムゾーンで今からの次の 10 回の実行を計算し、最大 366 日先まで探索します。バックグラウンドワーカーで評価するため、重い式でもタブは止まりません。
- 実行を読む最初の数回の実行を意図と照合します。「平日の 09:00」なら月曜から金曜の 9 時が並ぶはずで、そこに土曜がいれば OR トラップが名乗り出ています。
- 切り替えをまたぐ名前付きタイムゾーンを選び、次の夏時間切り替えが 366 日間のプレビュー内にあれば、その前後の予定を確認します。表示は現在時刻から始まり、任意の開始日は選べません。
- 明示的なエラー不正な式はエラーになります。366 日間に一致がなければ検索上限エラーとなり、1~9 件なら空欄ではなく部分的な結果を返します。
よくある質問
想定外の曜日に cron が動いたのはなぜですか?
cron で日曜日は 0 と 7 のどちらですか?
夏時間に左右されないスケジュールにするには?
スケジュールとパターンは同じ規律を共有します。
どちらも影響半径の大きい小さな文字列です。正規表現のための write-test-refactor ループを、タイムアウト付きのローカルワーカーで学びましょう。