ぱんだツールズぱんだツールズ

技術背景

CRON式の読み方・書き方 — 「* * * * *」を正しく理解する

約6分

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

位置フィールド値の範囲補足
10-59最小単位。標準では秒指定不可
20-2324時間制
31-31月末自動調整なし(2月30日を指定しても実行されない)
41-12JAN-DEC の文字略称も使える実装あり
5曜日0-70と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. ステップ値(*/NA-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 / LambdaUTC固定不可(計算でずらすしかない)
GitHub Actions の scheduleUTC固定不可
Kubernetes CronJobv1.25以降は spec.timeZone で指定可可(要バージョン)
Vercel / Cloudflare Cron TriggersUTC固定不可

たとえば「日本時間の毎朝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 EventBridge6(分・時・日・月・曜・年)? L # 使用可。日と曜日は同時指定不可
Spring Scheduler6(秒を追加)@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式説明ツールで日本語化して確認する

よくある質問

CRON式で「毎5分ごと」はどう書きますか?

分フィールドに「*/5」と書きます。完全形は「*/5 * * * *」です。これは0分・5分・10分…と5分刻みで実行することを意味します。同じく「*/15」は15分ごと、「*/30」は30分ごとになります。なお「*/7」のように60で割り切れない値を使うと、1時間の境目で間隔が不均一になる(55分の次が0分=5分間隔)点に注意してください。

CRON式で秒単位の指定はできますか?

標準(Vixie Cron・crontab)のCRON式は分が最小単位で、秒は指定できません。秒を扱えるのはSpring Scheduler・Quartz Scheduler・AWS EventBridge(拡張表現)など一部の拡張実装のみです。これらは左端に「秒」フィールドが追加され「0 */5 * * * *」(毎分5秒のところ、など)のような6フィールド形式になります。使う環境のドキュメントで対応を確認してください。

曜日フィールドの「0」と「7」の違いは何ですか?

多くのCRON実装では「0」も「7」も日曜日を表します。歴史的経緯で両方受け付ける実装が標準(POSIX準拠・Vixie Cron)です。月曜日は1、火曜日は2…土曜日が6で、日曜日が0または7という並びになります。ただし実装によっては0のみ受け付けるものもあるため、互換性を重視するなら「0」で統一するのが無難です。

日フィールドと曜日フィールドを両方指定するとどうなりますか?

標準のVixie Cronでは、日または曜日のどちらかがマッチすれば実行されます(OR条件)。たとえば「0 9 15 * 1」は「毎月15日の9時」または「毎週月曜の9時」に実行されます。一方、QuartzやAWS EventBridgeでは日と曜日を同時に「*」以外にすることを禁止しており、一方は必ず「?」(指定なし)にする必要があります。環境によって挙動が異なる代表例なので注意してください。

同じ時刻に2つのCRONジョブが重なると何が起きますか?

Cron自体はジョブの重複を制御しません。2つのエントリが同じ時刻を指していれば、両方が並行して起動します。重い処理が同じ分に集中するとCPU・I/Oが競合してサーバーが不安定になることがあります。対策として、実行時刻をずらす(0分と5分など)、flockなどのロック機構で排他制御する、ジョブ管理システム(Kubernetes CronJob・Airflowなど)を使うといった方法があります。

CRON式のタイムゾーンは何になりますか?

多くの実装ではサーバーのシステムタイムゾーンに従います。Linuxなら「/etc/timezone」や「TZ」環境変数、コンテナならDockerfileやKubernetesのPodSpecで設定したタイムゾーンです。注意すべきはクラウドサービスで、AWS EventBridge・GitHub ActionsのscheduleはUTC固定です。JSTで「毎朝9時」に動かしたい場合、UTCでは「0時」を指定する必要があります(9時間マイナス)。

「0 0 1 * *」と「@monthly」の違いは何ですか?

機能的には同じで、どちらも「毎月1日の0時0分」を意味します。「@monthly」「@daily」「@hourly」「@weekly」「@yearly」などはVixie Cronで使える特殊表記(ニーモニック)で、可読性を優先したいときに便利です。ただしAWS EventBridge・Kubernetes CronJobなど一部の実装では @記法に対応していないため、ポータビリティが必要なら「0 0 1 * *」のような通常表記を使うのが安全です。

CRON式を書いて実際にテストする方法はありますか?

まずは実行される時刻を確認するのが近道です。ぱんだツールズの「CRON式説明ツール」(/tools/cron-explainer)は入力したCRON式を日本語で解説し、次回実行時刻を表示します。実際のサーバーに仕込む前に机上で挙動を確認できます。ローカル環境で試す場合は「crontab -e」で登録し、「crontab -l」で確認、ログは「/var/log/cron」や「journalctl -u cron」で追えます。

この記事で紹介したツール