Cron 式の読み方
Cron は Linux とほとんどのジョブスケジューラが使う定時実行の文法です。スペースで区切られた複数のフィールドからなり、各フィールドが時間の 1 つの軸を表します。読み解くコツは文法を暗記することではなく、フィールド同士が「AND」の関係にあると理解することです。すべてのフィールドを同時に満たしたときだけ、ジョブは実行されます。
5 つのフィールドとは
- 1 番目 分:0〜59
- 2 番目 時:0〜23。24 時間制なので、午後 3 時は 15 と書きます
- 3 番目 日:1〜31
- 4 番目 月:1〜12
- 5 番目 曜日:0〜7。0 と 7 はどちらも日曜です(実装によっては 1 が月曜なので注意)
スケジューラが秒単位に対応している場合(Spring の @Scheduled(cron=...) や Quartz など)、先頭に秒のフィールドが増えて 6 段になります。同じ式を別の場所へ貼ると「想定より頻繁に動く」現象が起きるのはこのためです。5 段の書式なのにシステムが 6 段として解釈すると、フィールド全体が 1 つずつずれます。
5 つの書き方
- 具体値:
30は 30 分ちょうど。 - 範囲:
9-18は 9 から 18 まで、両端を含みます。 - リスト:
1,3,5はその 3 つの値すべて。 - ステップ:
*/5は開始値から 5 個おき。10-40/5と書けば 10 から 40 の間で 5 分おきになります。 - ワイルドカード:
*は「このフィールドは制限なし」。
これらは混ぜて使えます。たとえば 0,30 9-17 * * 1-5 は「月曜から金曜の 9 時から 17 時の間、毎時 0 分と 30 分に 1 回ずつ」です。
実際の式を分解してみる
*/5 9-18 * * 1-5 を例に、1 段ずつ見ていきます。
- 分
*/5:5 分おき(0、5、10…55) - 時
9-18:午前 9 時から午後 6 時 - 日
*:日付の制限なし - 月
*:月の制限なし - 曜日
1-5:月曜から金曜
合わせると「平日の 9:00 から 18:55 まで、5 分おきに実行」です。勤務時間中は高頻度でデータを更新し、終業後は止めるという、よくある構成です。
最も踏みやすい 3 つの罠
- 「日」と「曜日」を同時に指定すると「OR」になる。 Cron で最も直感に反する仕様です。
0 0 13 * 5と書くと、「13 日かつ金曜」のつもりでも、実際の意味は「毎月 13 日、または毎週金曜」で、頻度は十数倍になります。「AND」を表現したいなら発想を変えるか、スクリプト側で判定してください。 */nで 24 時間をまたぐ正確な周期は作れない。 分フィールドの*/7は実際には 0、7、14…56 で、次の時間はまた 0 から始まります。つまり 56 分の次は 4 分後です。厳密な周期(7 分おきなど)が必要なら、秒フィールドを使うか別のスケジューラを使ってください。- 年フィールドが存在しない。 標準の Cron では「2026 年だけ実行」は表現できません。年を限定したいならジョブのスクリプト側で判定するか、年に対応した拡張文法(Quartz は対応、標準の crontab は非対応)を使ってください。
systemd timer との違い
新しい Linux なら、crontab の代わりに systemd timer も使えます。書き方が異なり、crontab は 1 行で済みますが、systemd は .service と .timer の 2 ファイルが必要です。systemd の利点は OnCalendar のような読みやすい書式に対応し、前回の実行結果を記録でき、実行を逃した場合の補償も設定できること(Persistent=true)です。24 時間稼働しないマシンでは systemd timer のほうが確実です。crontab は停止中に逃したジョブを補償しません。
タイムゾーンにも注意してください。Cron はサーバーのローカル時刻を使います。コンテナの既定は UTC であることが多く、手元で確かめた「毎朝 8 時」が、コンテナ上では午後 4 時になることがあります。デプロイ後は必ずタイムゾーン設定を確認してください。
式をどう検証するか
頭の中で想像しないことです。この式を上の入力欄に貼れば、次の 10 回の実行時刻が一覧で出ます。時刻が合っているかを見るのが最速の検証で、「日と曜日が OR になる」といった罠も一目でわかります。0 0 13 * 5 と書いたなら、一覧には毎月 13 日と毎週金曜の両方が現れ、問題がすぐ露呈します。
解析は完全にブラウザ内で完結し、ネットワークは不要です。
よくある質問
0 6 * * * は何時ですか?
毎朝 6 時ちょうどです。1 番目の 0 が 0 分、2 番目の 6 が 6 時、後ろの 3 つはワイルドカードで制限なし。最もよく使われる書き方のひとつです。
@daily のような書き方に対応していますか?
標準の crontab はマクロを一組サポートしています。@daily(毎日 0 時)、@hourly(毎時)、@weekly、@monthly、@yearly、@reboot(起動後に 1 回)。本ツールは標準の数値式の解析に特化しているので、マクロは同等の式に置き換えてください。たとえば @daily は 0 0 * * * です。
曜日に 7 が使えるのはなぜ?
0 と 7 のどちらも日曜と定義されているからで、どちらを書いても同じです。ただし月曜を表したいときは 1 を使ってください。8 と書いてはいけません。一部のシステムでは曜日が 1〜7(1 が日曜)と定義されているので、プラットフォームを移すときは必ず確認してください。
予測時刻と実際の実行時刻がずれます
まずタイムゾーンを確認してください。コンテナやクラウド関数の既定は UTC が多く、日本時間とは 9 時間(中国標準時とは 8 時間)ずれます。次に、スケジューラが 5 段形式か 6 段形式かを確認してください。1 段足りない、あるいは多いと、フィールド全体がずれます。
今後 1 年分の実行時刻をすべて計算できますか?
本ツールは既定で 10 回分を表示し、ロジックの検証には十分です。総量を見積もりたい場合(ジョブの負荷評価など)は、スケジューラ付属の分析ツールを使うか、サーバー側で計算してください。