0 3 * * *を見て「毎日午前3時実行」と即答できますか?CRON(クーロン)はUnix系OSで定期実行を管理する仕組みとして 40年以上使われ続けている古株ですが、あの独特な5つの数字の羅列は慣れないと暗号にしか見えません。 この記事では、CRON式の5フィールドの意味から、ステップ・範囲・複数指定の記法、そして タイムゾーンでハマりがちな落とし穴まで、実例を交えて整理します。
CRON式は5つのフィールドでできている
標準的なCRON式は空白区切りで並ぶ5つのフィールドで構成されます。 左から「分・時・日・月・曜日」の順で、それぞれの値がマッチしたタイミングでコマンドが実行されます。
# フィールドの並び
* * * * *
分 時 日 月 曜日
(0-59)(0-23)(1-31)(1-12)(0-7)
# 例: 毎日午前3時
0 3 * * * command
| 位置 | フィールド | 値の範囲 | 補足 |
|---|---|---|---|
| 1 | 分 | 0-59 | 最小単位。標準では秒指定不可 |
| 2 | 時 | 0-23 | 24時間制 |
| 3 | 日 | 1-31 | 月末自動調整なし(2月30日を指定しても実行されない) |
| 4 | 月 | 1-12 | JAN-DEC の文字略称も使える実装あり |
| 5 | 曜日 | 0-7 | 0と7は両方日曜。SUN-SATの略称も可(実装次第) |
基本パターン早見表
まず覚えておきたいのは、「*」はそのフィールドのすべての値にマッチするという点です。 全部「*」なら「毎分実行」になります。頻出パターンを表にまとめました。
| CRON式 | 意味 | よくある用途 |
|---|---|---|
| * * * * * | 毎分 | 死活監視・キュー消化 |
| 0 * * * * | 毎時ちょうど(0分) | 軽量バッチ・集計 |
| 0 0 * * * | 毎日0時 | 日次バッチ・ログローテーション |
| 0 3 * * * | 毎日午前3時 | バックアップ・低負荷時のメンテ |
| 0 0 * * 0 | 毎週日曜0時 | 週次レポート・週次バックアップ |
| 0 0 1 * * | 毎月1日の0時 | 月次集計・請求処理 |
| 0 0 1 1 * | 毎年1月1日の0時 | 年次リセット |
記法の応用 — 「*」以外の書き方
「*」と数字以外に、各フィールドではステップ・範囲・複数指定の3種類の修飾が使えます。 これを組み合わせることで、かなり複雑なスケジュールを表現できます。
1. ステップ値(*/N・A-B/N)
「*/5」は「5刻みの値すべて」を意味します。分フィールドなら0・5・10・15…55に該当します。 範囲と組み合わせて「0-30/5」と書けば0分〜30分までの5分刻みになります。
# 5分ごとに実行
*/5 * * * *
# 2時間ごとに実行(0時・2時・4時…)
0 */2 * * *
# 朝9時〜18時の間、30分ごと
*/30 9-18 * * *
2. 範囲指定(A-B)
「1-5」のようにハイフンで連続する範囲を指定できます。曜日フィールドで「1-5」と書けば 月曜〜金曜(平日)の意味になります。
# 平日の朝9時に実行
0 9 * * 1-5
# 毎日9時〜17時の毎時0分に実行
0 9-17 * * *
3. 複数指定(A,B,C)
カンマで区切れば連続しない複数の値を並べられます。ステップ・範囲・複数指定はすべて同一フィールド内で 組み合わせ可能です。
# 1日と15日の0時に実行(月2回)
0 0 1,15 * *
# 朝9時・12時・18時に実行
0 9,12,18 * * *
# 平日の9時〜18時、15分と45分に実行
15,45 9-18 * * 1-5
よくあるパターン実例
実務で頻出する設定を、用途別にまとめました。コピペ前にCRON式説明ツールで日本語説明と次回実行日時を確認するとミスが減ります。
| 用途 | CRON式 | 意味 |
|---|---|---|
| ヘルスチェック | */5 * * * * | 5分ごと |
| 営業時間中の同期 | */10 9-18 * * 1-5 | 平日9〜18時、10分ごと |
| 深夜バックアップ | 0 2 * * * | 毎日午前2時 |
| 週次レポート | 0 9 * * 1 | 毎週月曜9時 |
| 月初バッチ | 0 0 1 * * | 毎月1日0時 |
| 月2回の締め処理 | 0 0 1,15 * * | 毎月1日と15日の0時 |
| 四半期集計 | 0 0 1 1,4,7,10 * | 1・4・7・10月の1日0時 |
タイムゾーンの罠 — UTCかJSTか
CRON式に時差の概念はありません。指定した時刻はそのシステムの基準タイムゾーンで解釈されます。 日本のサーバーでJSTならそのまま読めますが、クラウドサービスの多くはUTCが既定なので要注意です。
| サービス / 環境 | 既定タイムゾーン | 変更可否 |
|---|---|---|
| Linux / macOS の crontab | システムのTZ(/etc/timezone) | TZ環境変数で上書き可 |
| AWS EventBridge / Lambda | UTC固定 | 不可(計算でずらすしかない) |
| GitHub Actions の schedule | UTC固定 | 不可 |
| Kubernetes CronJob | v1.25以降は spec.timeZone で指定可 | 可(要バージョン) |
| Vercel / Cloudflare Cron Triggers | UTC固定 | 不可 |
たとえば「日本時間の毎朝9時」にGitHub Actionsを動かしたい場合、 JSTはUTCより9時間進んでいるので、UTCでは前日の0時を指定します。 つまり0 0 * * *(UTC 0時 = JST 9時) と書くのが正解です。
サマータイムのある国向けに動かす場合はさらに複雑になります。特に「深夜2時実行」を設定すると、 サマータイム切り替えの日にはその時刻がスキップまたは重複し、ジョブが二重実行されたり実行されなかったりします。 重要なジョブは2時〜3時帯を避けるのが実務上のコツです。
Vixie Cron と拡張CRONの違い
Linuxの標準実装であるVixie Cronは5フィールド構成ですが、一部のシステムは独自拡張を持っています。 どの環境で動かすかによって使える表現が変わる点に注意してください。
| 実装 | フィールド数 | 特殊記法 |
|---|---|---|
| Vixie Cron(標準) | 5(分・時・日・月・曜) | @daily / @hourly などのニーモニック |
| Quartz Scheduler(Java) | 6〜7(秒と年を追加) | ? L W # など豊富 |
| AWS EventBridge | 6(分・時・日・月・曜・年) | ? L # 使用可。日と曜日は同時指定不可 |
| Spring Scheduler | 6(秒を追加) | @daily ニーモニックも可 |
移植性を高めたい場合、特殊記法(?・L・W・#・@daily)に頼らず5フィールドで書くのが鉄則です。 逆にAWS EventBridgeやQuartzで「最終日の18時」のような要件を実現するなら、拡張記法を使うと簡潔に書けます。
まとめ
- CRON式は分・時・日・月・曜日の5フィールド。並びさえ覚えれば読めるようになる
- 「*」はそのフィールドの全値、「*/N」はN刻み、「A-B」は範囲、「A,B,C」は複数指定
- 日と曜日を同時指定するとVixie CronではOR条件、QuartzやAWSでは禁止——環境で挙動が変わる
- タイムゾーンはシステム依存。AWS EventBridge・GitHub Actions・Cloudflare CronはUTC固定
- 標準(5フィールド)と拡張(6〜7フィールド)で使える記法が異なるため、移植時は要確認
- 読み方に迷ったらCRON式説明ツールで日本語化して確認する