cron式の読み方・書き方:5つのフィールドとよく使う例
毎日午前2時にバックアップ、平日の午前9時にレポート送信、10分ごとに状態確認。cronで定期ジョブを設定するために必要なことをまとめました。
5つのフィールド
標準的なUnixのcron式は、空白で区切られた5つのフィールドからなります。分(0〜59)、時(0〜23)、日(1〜31)、月(1〜12)、曜日(0〜7、0と7はどちらも日曜)です。すべてのフィールドが一致したときにジョブが実行されます。
たとえば 0 2 * * * は、0分、2時、毎日、毎月、曜日を問わず、つまり毎日午前2時を意味します。アスタリスクは「すべての値」という意味です。
┌───── 分 (0-59)
│ ┌─── 時 (0-23)
│ │ ┌─ 日 (1-31)
│ │ │ ┌ 月 (1-12)
│ │ │ │ ┌ 曜日 (0-7, 日曜=0 または 7)
│ │ │ │ │
0 2 * * *
4つの特殊文字
この4つを組み合わせれば、ほとんどのスケジュールを表せます。MON や JAN のような名前を受け付けるシステムもあります。
- *(すべて):時フィールドの * は毎時を意味する。
- ,(列挙):1,15 は1日と15日を意味する。
- -(範囲):曜日フィールドの 1-5 は月曜から金曜を意味する。
- /(間隔):分フィールドの */10 は0、10、20…と10分ごとを意味する。5-59/15 のように開始値も指定できる。
よく使う例
式を書いたら、次の数回の実行時刻を計算して意図どおりか確認しましょう。間隔はジョブの開始時点ではなく0から数えることに注意してください。分フィールドの */45 は45分ごとではなく、毎時0分と45分に実行されます。
*/5 * * * * 5分ごと
0 * * * * 毎時0分
30 9 * * 1-5 平日の9時30分
0 0 1 * * 毎月1日の0時
0 18 * * 5 毎週金曜の18時
0 3 * * 0 毎週日曜の3時
0 9,18 * * * 毎日9時と18時
0 0 1 1 * 1月1日の0時
よくある落とし穴
最も有名な落とし穴は、日と曜日の両方を指定する場合です。0 0 13 * 5 は「13日の金曜日」に見えますが、標準のcronでは、どちらのフィールドも * でないときはORで結合されます。つまり毎月13日と毎週金曜日の両方で実行されます。
2つ目は「月末」です。標準の5フィールドのcronには月末を表す記号がありません。よくある回避策は、28〜31日に実行し、スクリプト側で翌日が1日かどうかを確認する方法です。Quartzのように L をサポートするスケジューラーもありますが、それらは秒を含む6〜7フィールドの形式で、標準のcronとは互換性がありません。
cronはどのタイムゾーンで動くのか
cronはサーバーのシステムタイムゾーンに従います。クラウドのサーバーの多くはUTCで動いているため、日本時間の午前9時に送るつもりのレポートが日本時間の午後6時に送られることがあります。日本時間(JST)の午前9時はUTCの0時なので、UTCのサーバーでは 0 0 * * * と書きます。
GitHub ActionsやKubernetesのCronJobも既定ではUTCです。夏時間のある地域に合わせたスケジュールでは、現地の実行時刻が年に2回1時間ずれることを想定しておきましょう。
運用のコツ
AIBIZAPのcron生成ツールでは「毎日」や「毎週」を選ぶだけで式が作られるので、構文を覚えなくても正しいスケジュールを設定できます。
- 重いジョブは全部を0分に始めず、7分や23分のように分散させる。
- 次の実行までに終わらない可能性があるなら、ロックを使って重複実行を防ぐ。
- cronの環境変数やPATHは対話シェルとは異なるので、スクリプトでは絶対パスを使う。
- 実行のたびに出力をログに残し、失敗に気づけるようにする。