cron式の書き方を図解|5つのフィールドと実務でよく使う設定例
cron は、指定した時刻にコマンドを自動実行する仕組みです。バッチ処理やバックアップの定期実行に欠かせませんが、0 3 * * 1 のような記法は一見して意味が分かりません。この記事では、cron 式の構造を分解して、実務で使う設定を書けるようにします。
cron式は5つのフィールドでできている
cron 式は、スペース区切りの 5 つのフィールドで構成されます。
┌────────── 分(0-59)
│ ┌──────── 時(0-23)
│ │ ┌────── 日(1-31)
│ │ │ ┌──── 月(1-12)
│ │ │ │ ┌── 曜日(0-7、0と7が日曜)
│ │ │ │ │
* * * * *
左から「分・時・日・月・曜日」の順です。この順番を覚えていないと読み書きできないので、まずここだけは押さえてください。
例として 0 3 * * 1 を分解します。
| フィールド | 値 | 意味 |
|---|---|---|
| 分 | 0 | 0分 |
| 時 | 3 | 3時 |
| 日 | * | 毎日 |
| 月 | * | 毎月 |
| 曜日 | 1 | 月曜 |
合わせると「毎週月曜日の午前3時0分」になります。
4つの記号の使い分け
各フィールドでは、次の 4 種類の記号が使えます。
| 記号 | 意味 | 例 | 読み方 |
|---|---|---|---|
* | すべての値 | * * * * * | 毎分 |
, | 複数指定 | 0 9,12,18 * * * | 9時・12時・18時 |
- | 範囲指定 | 0 9-18 * * * | 9時から18時まで毎時 |
/ | 間隔指定 | */15 * * * * | 15分おき |
/ は「〜おき」を意味します。*/15 は「0分から始めて15分間隔」なので、0分・15分・30分・45分に実行されます。
記号は組み合わせられます。0 9-18/2 * * 1-5 なら「平日の9時から18時まで、2時間おき」です。
実務でよく使う設定例
そのまま使える形で並べます。
| cron式 | 実行タイミング |
|---|---|
*/5 * * * * | 5分おき |
0 * * * * | 毎時0分 |
0 */6 * * * | 6時間おき(0時・6時・12時・18時) |
0 3 * * * | 毎日 午前3時 |
30 2 * * * | 毎日 午前2時30分 |
0 9 * * 1-5 | 平日のみ 午前9時 |
0 0 * * 0 | 毎週日曜 0時 |
0 4 1 * * | 毎月1日 午前4時 |
0 0 1 1 * | 毎年1月1日 0時 |
0 9,17 * * 1-5 | 平日の9時と17時 |
定期バッチをいつ実行すべきか
深夜帯に集中させると、サーバー負荷が特定の時間に偏ります。実務では次を意識してください。
- 0時ちょうどは避ける — 多くのジョブが集中しやすい時間帯です
- 毎日実行するバッチは分をずらす —
0 3,10 3,20 3のように分散させる - 日次集計は日付が変わってしばらく後に — 当日分のデータ書き込みが完了してから実行する
間違えやすいポイント
「日」と「曜日」を両方指定すると OR になる
これは cron の仕様で最も誤解されやすい点です。
0 0 1 * 1
一見「毎月1日、かつ月曜日」に見えますが、実際は「毎月1日、または毎週月曜日」として解釈されます。AND ではなく OR です。
「毎月第1月曜日」のような条件は、標準の cron 式では表現できません。実現するには、毎週月曜に実行して、スクリプト側で日付が 1〜7 の範囲かを判定します。
# 毎週月曜に実行し、その月の第1週かを判定
0 0 * * 1 [ "$(date +\%d)" -le 07 ] && /path/to/script.sh
なお、crontab 内では % が特別な意味(改行)を持つため、\% とエスケープする必要があります。これも見落としやすい罠です。
曜日の 0 と 7 はどちらも日曜
曜日フィールドは 0〜7 で、0 と 7 の両方が日曜を指します。月曜は 1、土曜は 6 です。
「0 が月曜」ではありません。 週の始まりを月曜と考える習慣があると間違えやすいので注意してください。
タイムゾーンはサーバー設定に依存する
cron はサーバーのシステムタイムゾーンで動作します。サーバーが UTC 設定なら、0 3 * * * は UTC の午前3時、すなわち日本時間の正午に実行されます。
クラウド環境のインスタンスは UTC がデフォルトのことが多いため、必ず確認してください。
# 現在のタイムゾーンを確認
timedatectl
date
crontab 内でタイムゾーンを指定できる実装もあります。
CRON_TZ=Asia/Tokyo
0 3 * * * /path/to/script.sh
ただし、これは cron の実装によって対応状況が異なります。動作するかどうかは実環境で確認してください。
環境変数が読み込まれない
cron から実行されるスクリプトは、ログインシェルの環境変数を引き継ぎません。手動では動くのに cron では失敗する場合、ほぼこれが原因です。
- コマンドは絶対パスで書く(
pythonではなく/usr/bin/python3) - スクリプト内で必要な環境変数を明示的に設定する
- または crontab の冒頭で
PATHを定義する
PATH=/usr/local/bin:/usr/bin:/bin
0 3 * * * /usr/bin/python3 /opt/app/batch.py >> /var/log/batch.log 2>&1
実行結果を捨てない
>> ログファイル 2>&1 を付けておかないと、エラーが出ても気づけません。cron はデフォルトで実行結果をメールで送ろうとしますが、メール設定がない環境では単に消えます。
式が正しいか確認する
書いた cron 式が意図どおりか、頭の中だけで検証するのは危険です。特に / と , を組み合わせた式は勘違いしやすくなります。
Cron式ジェネレーターツールでは、式を入力すると日本語での説明と次回以降の実行日時が表示されます。「毎月1日と毎週月曜が OR になっている」といった誤りも、実行予定日を見れば一目で分かります。
本番環境に設定する前に、必ず次の 2 点を確認してください。
- 次回実行日時が想定どおりか
- 想定より高い頻度で実行されないか(
*の付け忘れによる毎分実行は事故につながります)
まとめ
- フィールドは左から「分・時・日・月・曜日」
*すべて、,複数、-範囲、/間隔- 日と曜日を両方指定すると AND ではなく OR
- 曜日は 0 と 7 が日曜
- タイムゾーンと環境変数はサーバー設定に依存する
- 設定前にジェネレーターで次回実行日時を確認する
cron の事故は「意図より多く実行される」形で起きることがほとんどです。設定前の確認を習慣にしてください。