cron は Unix 系システムで繰り返しジョブをスケジュールする仕組みで、その式の形式は crontab にとどまらず、CI パイプライン、Kubernetes CronJob、各種クラウドスケジューラでも使われます。構文は最初こそ難解に見えますが、実は空白で区切られた 5 つのフィールドです。
最も一般的なスケジュールを、私たちのツールはこう読みます。 cron ジェネレーターに
0 9 * * 1-5を入力すると、各フィールドを読み返します。Minute: 0 Hour: 9 Day of month: every Month: every Day of week: Mon-Friここで人がつまずく点が 2 つ見えます。「日」と「曜日」がどちらも
everyで、両方とも無制限なら単に毎日実行されます。しかし両方に制限を付けると、両者は AND ではなく OR として振る舞います。これが cron で最も多いバグです。そして1-5が月〜金なのは、週が 0 = 日曜から始まるからです。
5 つのフィールド
┌── 分 (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 分 |
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 ジェネレーターの出力です。5 つのフィールドを解析して言葉で読み返すので、桁をずらして書いた間違いを最短で見つけられます。
| 式 | ツールの読み |
|---|---|
* * * * * | 分: すべての 時: すべての 日: すべての 月: すべての 曜日: すべての |
*/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 日の金曜」だけではありません。迷ったら実際の実行時刻で確認しましょう。
誰もがつまずく 2 つの式は 1 文字しか違いません。0 0 1 * * は 分: 0 時: 0 日: 1 月: すべての 曜日: すべての —— 毎月 1 日。0 0 * * 1 は 分: 0 時: 0 日: すべての 月: すべての 曜日: 月 —— 毎週月曜。3 番目が日、5 番目が曜日です。多くの実装では両方を指定すると AND ではなく OR になるため、0 0 1 * 1 は毎月 1 日および毎週月曜に動きます。
本番前に検証を
cron を信頼する最も安全な方法は、「実際に発火する時刻」を見ることです。Cron 式ジェネレーターは各フィールドを分かりやすく説明し、ローカル時間での次回実行時刻を一覧表示します。ワンクリックのプリセットもあり、すべてブラウザ内で動作します。
関連ツール
- Unix タイムスタンプも扱うならタイムスタンプ変換。
ショートカット文字列
多くの cron は、5 つのフィールドの代わりに名前付きショートカットを受け付けます:
| ショートカット | 相当する式 | 実行タイミング |
|---|---|---|
@yearly(または @annually) | 0 0 1 1 * | 年 1 回、1 月 1 日 |
@monthly | 0 0 1 * * | 毎月 1 日 |
@weekly | 0 0 * * 0 | 毎週日曜 |
@daily(または @midnight) | 0 0 * * * | 毎日深夜 |
@hourly | 0 * * * * | 毎時 |
@reboot | —— | 起動時に 1 回 |
フィールド数の違いにも注意しましょう。Spring の @Scheduled、Quartz、一部のクラウドスケジューラは先頭に秒フィールドを足して 6 つになり、AWS EventBridge は 6 フィールド形式で「日」と「曜日」の同時指定を禁止しています。5 フィールドの式を 6 フィールドのパーサーに貼ると、まるごと 1 つずれます。
タイムゾーンとサマータイム
古典的な crontab にはタイムゾーンのフィールドがなく、サービスが動くマシンのローカル時間で発火します。Linux ではファイルに CRON_TZ=UTC(または TZ)の 1 行を書いて上書きでき、多くのクラウドスケジューラは代わりにタイムゾーンの選択肢を用意しています。地域をまたいで共有するものは、誰も時差を計算せずに済む UTC が安全な既定値です。
サマータイムの切り替えは典型的な落とし穴です。時計が進むと、飛ばされた 1 時間に入るジョブ(例:30 2 * * *)はその日実行されないことがあり、戻ると、重複する 1 時間のジョブは 2 回走ることがあります。重要なジョブは 01:00–03:00 の外に置くか、UTC で動かしましょう。エポック秒も扱うなら、Unix タイムスタンプ完全ガイドがそれらと壁時計の時刻の対応を解説しています。
手早い FAQ
- 範囲と間隔は組み合わせられる? はい——
0-30/10は 0・10・20・30 です。 - 「時」フィールドの
*/2の意味は? 1 時間おき:0・2・4⋯22。 - cron は逃したジョブを後で実行する? しません。予定時刻にマシンが停止していれば、素の cron は単に飛ばします——追いかけ実行が要るなら
anacronを。