Cron式→systemdタイマー変換ツール
cron式(分 時 日 月 曜日)をsystemdタイマーのOnCalendar=構文に変換する無料ツール。日と曜日を同時指定した場合のOR条件の注意も警告表示し、Docker/Kubernetes環境でのcron移行に便利です。
cronフィールドとsystemdコンポーネントの対応表
cron式の5つのフィールドは、systemdのOnCalendar=構文では以下のように対応します。
| 位置 | cronフィールド | systemdでの対応箇所 |
|---|---|---|
| 1 | 分 | 時刻部分の分(HH:MM:SS の MM) |
| 2 | 時 | 時刻部分の時(HH:MM:SS の HH) |
| 3 | 日(日付) | 日付部分の日(年-月-日 の 日) |
| 4 | 月 | 日付部分の月(年-月-日 の 月) |
| 5 | 曜日 | 曜日プレフィックス(例: Mon、Mon..Fri) |
cronに秒フィールドはないため、systemd側の秒は常に「00」になります。また日付・曜日ともに無制限(*)の場合、systemd側の年-月-日部分は省略できます。
cronの曜日番号とsystemdの曜日略称の対応表
cronでは曜日を0〜7の数値で表しますが、systemdでは英語の曜日略称を使います。
| cronの曜日番号 | systemdの曜日略称 |
|---|---|
| 0 (7) | Sun |
| 1 | Mon |
| 2 | Tue |
| 3 | Wed |
| 4 | Thu |
| 5 | Fri |
| 6 | Sat |
よくある変換例
| cron式 | OnCalendar= | 意味 |
|---|---|---|
| * * * * * | OnCalendar=*-*-* *:*:00 | 毎分実行します(cronの「* * * * *」相当)。 |
| */15 * * * * | OnCalendar=*:00/15:00 | 15分ごとに実行します。 |
| 0 9 * * 1-5 | OnCalendar=Mon..Fri 09:00:00 | 平日(月〜金)の9時0分に実行します。 |
| 0 0 1 * * | OnCalendar=*-*-01 00:00:00 | 毎月1日の0時0分に実行します。 |
| 0 0 1 1 * | OnCalendar=*-01-01 00:00:00 | 毎年1月1日の0時0分に実行します。 |
| 0 0 1 * 1 | OnCalendar=Mon *-*-01 00:00:00 | 日(1日)と曜日(月曜日)の両方を指定した例。cronではOR条件(どちらか一方で実行)ですが、systemdではAND条件(両方を満たす日のみ実行)になるため、変換結果は元のcron式より実行頻度が少なくなる点に注意してください。 |
日(日付)と曜日の両方を「*」以外に制限したcron式は、systemdのOnCalendar構文では正確に変換できません(cronはOR条件、systemdはAND条件のため)。このようなケースでは、2つの別々のsystemdタイマーに分割することを検討してください。
cron式をsystemdタイマーへ書き換える
`cron` から `systemd` のタイマーへ移す際に必要なのが、`分 時 日 月 曜日` という5つのフィールドを `OnCalendar=` の書式へ置き換える作業です。このツールはcron式を入力するだけで対応する `OnCalendar=` を生成し、あわせて注意すべき点を警告として示します。
**この変換で最も重要なのは、日(日付)と曜日を同時に指定したときの扱いです。** cron はこの2つを **OR** で解釈します。`0 0 1 * 1` は「毎月1日**または**毎週月曜日」という意味になり、月に5回前後実行されることもあります。ところが **systemd の `OnCalendar=` は同じ指定を AND として扱います。** つまり「1日**かつ**月曜日」となり、年に1〜2回しか動きません。**機械的に置き換えると、実行頻度が静かに変わってしまう**わけです。このツールはその組み合わせを検出して警告します。
変換の手順
- cron式を入力する `分 時 日 月 曜日` の5つのフィールドを空白区切りで書きます。
- 生成された OnCalendar= を確認する 対応する systemd の書式が得られます。
- 警告を読む **日と曜日を同時に指定している場合は、意味が変わる旨が示されます。**
- タイマーユニットへ書き写す `.timer` ファイルの `[Timer]` セクションへ貼り付けます。
使いこなすためのヒント
- 日(日付)と曜日の両方を「*」以外に指定すると、cronのOR条件をsystemdのAND条件では正確に表現できません。この場合は変換結果の警告を確認し、必要なら2つのタイマーに分割してください。
- Alpine LinuxベースのDockerイメージなど、一部の最小構成コンテナにはcronデーモン自体が含まれていないことがあり、systemdタイマーへの移行が有効な代替手段になります。
- 生成されたOnCalendar行は「systemd-analyze calendar」コマンドに渡すことでも構文チェックでき、次回実行予定時刻まで確認できます。
- systemdタイマーは.timerユニットと、実際の処理を書く.serviceユニットの2ファイルセットで構成される点がcrontabの1行設定と異なります。
- 曜日と日付を同時に使わない単純なスケジュール(毎時・毎日・毎週など)であれば、この変換は常に正確に一致します。
活用シーン
コンテナ環境へ移行する
**コンテナにはcronデーモンが入っていないことが多く、systemdタイマーや別の仕組みへ移す必要があります。**
実行ログを残したい
systemdタイマーなら journald に記録が残り、後から追えます。
依存関係を持たせたい
**他のユニットの起動後に走らせるといった指定は、cronにはできません。**
既存のスケジュールを棚卸しする
cron式をまとめて変換すると、意図した頻度になっているかを見直す機会になります。
スケジューラーの用語
- cron式
- `分 時 日 月 曜日` の5フィールドで実行時刻を表す書式です。**日と曜日はORで解釈されます。**
- OnCalendar=
- systemdタイマーで実行時刻を指定するキーです。**日と曜日はANDで解釈されます。**
- タイマーユニット
- `.timer` という拡張子のファイルで、同名の `.service` を起動します。
- Persistent=
- **タイマーが動くべき時刻にシステムが止まっていた場合、起動後に取り戻して実行する指定です。** cronの `anacron` に近い働きをします。
- AccuracySec=
- 実行時刻の許容誤差です。既定では1分の幅があるため、厳密に合わせたい場合は指定します。
- journald
- systemdのログ収集の仕組みです。タイマーで起動したジョブの出力もここに残ります。
よくある質問
余談ですが ― cronからsystemdタイマーへ
systemdはLinuxの起動処理を管理する初期化システムとして2010年頃に登場して以来、多くのディストリビューションの標準になりました。その一部であるsystemdタイマーは、cronと同様に定期実行の仕組みを提供しますが、依存関係の解決・実行ログの一元管理(journalctl)・失敗時のリトライ設定など、cronにはなかった機能を備えています。
一方でDockerやKubernetesのようなコンテナ環境では、イメージサイズを軽量に保つためにcronデーモンをあえて含めないベースイメージが増えています。こうした環境でジョブの定期実行を行う場合、Kubernetes CronJobのようなオーケストレーター側の仕組みを使うか、ホストがsystemdベースであればsystemdタイマーに委ねるのが現実的な選択肢になります。
OnCalendar=構文はcronの5フィールドよりも表現力が高く、年単位の指定や秒単位の精度にも対応していますが、その表現力の違いゆえに一部のcron式(日と曜日を同時に制限したOR条件)は単純な変換では意味が変わってしまいます。本ツールがこの点を明示的に警告するのは、移行時に気づきにくい落とし穴を早期に発見してもらうためです。