cron式を構築する方法
Cron式は、Linux、クラウドプラットフォーム、CI/CDパイプライン、タスクスケジューラで繰り返しスケジュールを定義する標準的な方法です。構文はコンパクトですが直感的ではありません。ビジュアルなcronジェネレーターを構築すると、ジョブがいつ実行されるか正確に表示され、デプロイ前によくあるエラーをキャッチし、自動化の最もエラーが起きやすい部分から推測を取り除けます。5つのフィールド、特殊文字、最もよくある落とし穴を理解すれば、自信を持って任意の繰り返しスケジュールを指定できます。
cronの簡単な歴史
最初のcronは1979年頃にVersion 7 UnixのBrian Kernighanから来ました。それは毎分設定を再読み込みし、期限のものを何でも実行しました。Paul Vixieは1987年にそれを書き直し、現在Vixie cronと呼ばれるものになりました。これはほとんどのLinuxディストリビューションが今も出荷するバージョンです。Vixie cronは、ユーザーごとのcrontab、環境変数、@rebootキーワード、形式を非管理者にも使いやすくするいくつかの生活の質を向上させる機能を追加しました。
5フィールドの構文は40年以上、ほとんど変わっていません。Amazon EventBridge、Google Cloud Scheduler、Kubernetes CronJob、GitHub Actions、GitLab CI、Jenkins、Airflow、n8n、その他多くのシステムが、わずかな拡張だけで同じコンパクトな形式を消費します。その安定性こそが、cronを一度学んで二度と学び直さない価値のあるものにしています。スキルは時計で動作する自動化のどこにでも転送可能です。
Cron構文
標準のcron式は、スペースで区切られた5つのフィールドを持ちます。各フィールドは時間の1スライスをコントロールし、すべてのフィールドが現在の瞬間に一致するとジョブが実行されます。
┌───────────── 分(0から59)
│ ┌───────────── 時(0から23)
│ │ ┌───────────── 日(1から31)
│ │ │ ┌───────────── 月(1から12、またはJAN-DEC)
│ │ │ │ ┌───────────── 曜日(0から6、Sun=0、またはSUN-SAT)
│ │ │ │ │
* * * * *
フィールドは時、分、月についてANDで結ばれますが、日と曜日はVixie cronではORで結ばれます。これは、0 12 1 * 1が毎月1日に発火し、毎週月曜の正午にも発火することを意味します。1日に当たる月曜だけではありません。この罠は初めての人をほぼ全員捕まえます。
一般的なcronスケジュール
最も頻繁に手を伸ばすパターン:
| スケジュール | 式 | 意味 |
|---|---|---|
| 毎分 | * * * * * | 60秒ごとに実行 |
| 5分ごと | */5 * * * * | :00、:05、:10、:15で |
| 15分ごと | */15 * * * * | :00、:15、:30、:45で |
| 毎時 | 0 * * * * | 毎時の先頭で |
| 2時間ごと | 0 */2 * * * | 00:00、02:00、04:00で |
| 毎日真夜中 | 0 0 * * * | 1日に1回00:00で |
| 毎日午前9時 | 0 9 * * * | 1日に1回09:00で |
| 1日2回 | 0 9,21 * * * | 09:00と21:00で |
| 毎週月曜午前8時 | 0 8 * * 1 | 月曜の週1回 |
| 平日午後6時 | 0 18 * * 1-5 | 月曜から金曜 |
| 毎月1日 | 0 0 1 * * | 1日の真夜中、毎月 |
| 四半期ごと | 0 0 1 */3 * | 1月1日、4月1日、7月1日、10月1日 |
| 毎週日朝 | 0 7 * * 1-5 | 月から金の07:00 |
| 日曜正午 | 0 12 * * 0 | 日曜の週1回 |
多くのシステムは、同等の5フィールド式に展開されるショートハンドエイリアスも受け入れます: @yearly、@monthly、@weekly、@daily、@hourly、@reboot。これらは簡潔ですが普遍的ではないので、依存する前にプラットフォームを確認してください。
cron式を構築する手順
- 粒度を選ぶ: 毎分、毎時、1日1回、週1回、または月1回が必要ですか?ニーズを満たす最も粗い設定から始めてください。
- ビジュアルコントロールを使う: ドロップダウンから分、時、日、月、曜日の値を選択します。または「毎時」や「毎日真夜中」のようなプリセットから始めて調整します。
- 次の実行時刻をプレビュー: ジェネレーターは次の5つの実行時刻を表示し、スケジュールが期待通り発火するかを確認できます。
- タイムゾーンを健全性チェック: プレビューはローカル時刻ではなく、ジョブを実行するサーバーまたはスケジューラのタイムゾーンと一致する必要があります。
- 式をコピーして、crontab、GitHub Actions YAML、AWS EventBridgeルール、または使うスケジューラーに貼り付けます。
- 最終スケジュールをコミットする前に短い間隔でテスト: 素早い
*/5 * * * *はジョブが発火することを証明します。2、3回の実行が着地したら、実際の式に交換します。
特殊文字と演算子
cronは任意のフィールド内で小さくて強力な演算子セットをサポートします。
| 文字 | 意味 | 例 |
|---|---|---|
* | すべての値 | * * * * * = 毎分 |
*/n | n番目ごと | */15 * * * * = 15分ごと |
, | 複数の離散値 | 0 8,12,18 * * * = 午前8時、正午、午後6時 |
- | 包括範囲 | 0 9-17 * * * = 午前9時から午後5時の毎時 |
n-m/k | ステップ付き範囲 | 0 9-17/2 * * * = 9、11、13、15、17 |
? | 特定値なし(Quartzのみ) | 0 0 ? * MON(Javaスケジューラ) |
L | 最後(AWS、Quartz) | DoMのL = 月の最後の日 |
W | 最も近い平日(AWS、Quartz) | 15W = 15日に最も近い平日 |
# | N番目の曜日(AWS、Quartz) | MON#2 = 月の2番目の月曜 |
@hourly | ショートハンド | 0 * * * *と同じ |
バニラのVixie cronは最初の5行のみをサポートします。高度な演算子(L、W、#、?)はJavaスケジューリングライブラリのQuartzから来ており、AWS EventBridgeとその他のいくつかのクラウドスケジューラーに採用されました。これらは可搬性がないため、汎用Linuxボックスで実行する必要のあるコードに混ぜないでください。
異なるプラットフォームでのcron
cronは単一の標準ではなく、関連する構文のファミリーです。スケジューラーがどの方言を話すかを知ることは、デバッグの何時間も節約します。
| プラットフォーム | フィールド | 備考 |
|---|---|---|
| Vixie cron(Linux) | 5 | クラシック。*/n、範囲、リスト、高度な演算子なし |
| BSD cron | 5 | Vixieに似ているが環境にわずかな違い |
| crontab.guru | 5 | Vixieの意味論を反映するWebベースパーサー |
| GitHub Actions | 5 | Vixie構文、UTCで実行、少なくとも5分の解像度 |
| GitLab CI | 5 | Vixie構文、インスタンスタイムゾーンで実行 |
| AWS EventBridge | 6 | 年を追加。曜日は1から7を使う(Sun=1)、L/W/#をサポート |
| Google Cloud Scheduler | 5 | Vixie構文プラスタイムゾーン設定 |
| Kubernetes CronJob | 5 | @ショートカット付きのVixie構文 |
| Quartz(Java) | 6または7 | 先頭に秒、オプションで年を追加 |
| systemd timers | OnCalendar形式 | cronではないが、よりクリアな構文で同じ問題を解決 |
複数のプラットフォームで実行する必要のあるスケジュールを書くなら、すべてのシステムが理解する保守的な5フィールドサブセットに固執してください。L、W、#に手を伸ばすのは、目的地がそれらをサポートすると分かっているときだけです。
よくある落とし穴
- 日と曜日はORで結ばれる:
0 9 15 * 1のような式は、毎週月曜と毎月15日の両方で発火し、15日が月曜に当たるときだけではありません。交差させるには、通常は外部ラッパーまたは異なるスケジューラーが必要です。 - タイムゾーンの混乱: サーバーcrontabはほぼ常にUTCで実行されます。東部時間の午前9時が必要なら、冬は
0 14 * * *UTC、夏は夏時間のため0 13 * * *UTCです。タイムゾーンヒントをサポートするスケジューラーを使うか、すべてをUTCに正規化してください。 - 夏時間の遷移: 02:30ローカル時刻にスケジュールされたジョブは、時計が戻されるとき2回実行されることがあり、進めるときはまったく実行されないかもしれません。01:00から03:00の窓の外に敏感なジョブをスケジュールするか、UTCを使ってください。
- Vixieの
MAILTOの罠: ジョブがstdoutに何かを印刷すると、Vixie cronはcrontabを所有するユーザーに出力をメールします。メールリレーのないサーバーでは、これは/var/spool/mailを素早く満たします。>>/var/log/myjob.log 2>&1で出力をログファイルにリダイレクトしてください。 - 環境はログインシェルではない: cronは取り除かれた環境で実行されます。
.bashrcからのPATHなし、virtualenvなし、nvmなし。crontabの先頭で必要な変数を設定するか、絶対パスでスクリプトを呼び出してください。 - パーセント記号はエスケープが必要: Vixie crontabでエスケープされていない
%は、コマンド内の改行文字として解釈されます。コマンドがリテラルなパーセント記号を必要とする場合、つねに\%としてエスケープしてください。たとえばdate +"%Y-%m-%d"の呼び出しで。 - 長時間実行されるジョブの重複: cronは、前のジョブがまだ実行中だからといって実行をスキップしません。ジョブが間隔より長くかかる可能性があるなら、ロックファイル(
flock、setlock)でラップするか、並行性を扱うジョブランナーを使ってください。 - 59分でのオーバーフロー:
*/40 * * * *は40分ごとに発火しません。ステップ値がフィールドの境界を回り込むため、毎時の0分と40分に発火します。真の40分間隔には、より豊富なスケジューラーが必要です。 - 分フィールドの
0を忘れる:* 9 * * *は09:00ではなく、09:00から09:59まで毎分実行されます。時間ごとに1回の発火が欲しいなら、分フィールドに明示的な値が必要です。 - cronはラップトップで信頼できない: anacronがそのために存在します。Vixie cronはスリープ後に見逃した実行に追いつかないため、03:00にスケジュールされた毎日のバックアップは、その時間にラップトップが閉じていたら実行されません。anacron、
Persistent=trueのsystemdタイマー、またはmacOSのlaunchd plistを使ってください。
cronの代替
一部のワークロードでは、cronの粗い分解像度と簿記の欠如が痛み始めます。最も一般的なアップグレード:
| ツール | 強み | 選ぶとき |
|---|---|---|
| systemd timers | クリアなOnCalendar構文、再起動間で永続、ユニットと統合 | すでにsystemdを実行しており、より豊富なロギングが欲しい |
| Anacron | スリープ後に見逃した実行に追いつく | ラップトップやつねにオンではないマシン |
| Airflow / Dagster | DAG依存関係、リトライ、可観測性 | マルチステップデータパイプライン |
| Temporal | ステートフルワークフロー、正確に1回の保証 | サービス間の長時間オーケストレーション |
| AWS EventBridge | マネージド、Lambda、S3、SQSと統合 | AWSでのクラウドネイティブなもの |
| GitHub Actions | パブリックリポジトリに無料、ホストランナーで実行 | CIに隣接するスケジュールジョブ |
| cronトリガーのサーバーレス関数 | 保守するサーバーなし | Lambdaに収まる軽量タスク |
cronは大多数の1回限りの繰り返しジョブに対する正しい答えのままです。他のツールは、状態、リトライ、依存関係、マシン間の調整が必要なときに輝きます。
プライバシーとcronジェネレーター
cron式ジェネレーターは完全にブラウザ内で動作します。構築したスケジュール、次の実行時刻のプレビュー、コピーされた式は当社のサーバーに触れません。どの式が生成されたかのログも、どのプリセットが人気かのテレメトリも、あなたが取り組んでいたスケジュールを再構築する方法もありません。cron式は表面上は個人データではありませんが、ジョブのスケジュール(夜間のデータベースエクスポート、週次の請求実行、毎時のパートナーへの同期)はビジネスがどう運営されているかについて多くを明かす可能性があります。その情報をクライアントサイドに保つことで、インフラパターンを第三者に偶然漏らすのを避けられます。スケジュールを選ぶような日常のタスクには、プライバシーのデフォルトはそれらのスケジュールが表すものの機密性に一致すべきです。
よくある質問
cron式の形式は?
標準的なcron式には、スペースで区切られた5つのフィールドがあり、分(0-59)、時(0-23)、月の日(1-31)、月(1-12)、曜日(0-6、0は日曜日)を表します。アスタリスク(*)はそのフィールドの「すべての」値を意味します。
cronで*/5は何を意味しますか?
*/5構文は「5ごと」を意味します。分フィールドでは、*/5は5分ごと(0、5、10、15...)を意味します。時フィールドでは、*/5は5時間ごとを意味します。これは任意のフィールドで機能します。
cron式はすべてのプラットフォームで同じですか?
5フィールド形式は、Linux cron、AWS EventBridge、GitHub Actions、ほとんどのスケジューリングシステムで標準です。一部のプラットフォームは秒または年用に6番目のフィールドを追加します。プラットフォームのドキュメントを確認してください。
毎月の最終日にスケジュールするには?
標準のcronには「最終日」キーワードはありません。スクリプトでの日付チェック付きの毎日実行などの回避策を使用するか、プラットフォーム固有の拡張機能を使用してください(AWS EventBridgeはLを「last」としてサポート)。
Why did my cron job not run at the expected time?
The most common cause is timezone confusion. Server cron usually runs in UTC, not your local time. Other causes include the server being asleep at the scheduled minute, the user crontab not being installed, or PATH/environment differences between your shell and cron's stripped-down environment.
What is the difference between 0 in the day-of-week field and 7?
Both 0 and 7 represent Sunday in classic Vixie cron, which uses 0-6 plus an alias for 7. Some implementations (notably AWS EventBridge) use 1-7 with Sunday as 7 and Monday as 1, so always check your platform's documentation before assuming.