Linuxでジョブをスケジューリングする:cronとsystemd timerの比較
Linuxシステム管理において「いつ」ジョブが実行されるかは「何」を実行するかと同じくらい重要です。
最も古くから使われているのはcron、最近のディストリビューションではsystemdが標準になったことで、systemd timerを使うケースも増えています。
この記事では両者を比較し、実際にどのような場面でどちらを使うと良いかを整理します。
1. なぜcronとsystemd timerを比較するのか?
多くのLinuxサーバーでは次のような要件があります。
- 毎朝3時にバックアップを実行
- 5分ごとにヘルスチェックスクリプトを実行
- 毎週日曜日にログを圧縮・整理
- 起動後1分で一度だけ実行する初期化作業
従来はすべてcronで処理していましたが、最近では多くのディストリビューションがsystemdをデフォルトのinitシステムとして採用し、systemd timerが強力な代替手段として登場しています。
2. cronの基本概念
2.1 cronとは?
cronは古いUnix/Linuxスケジューラです。
決められた時間・周期でコマンドを実行し、設定は主にcrontabファイルで管理します。
2.2 cron設定の場所
- システム全体:
/etc/crontab,/etc/cron.d/ - ユーザー別:
crontab -eで編集されるper-user crontab
例として、毎朝3時にバックアップスクリプトを実行する設定:
0 3 * * * /usr/local/bin/backup.sh
フィールドの意味は次の通りです。
分 時 日 月 曜日 コマンド
0 3 * * * /usr/local/bin/backup.sh
2.3 cronのメリット
- 長年にわたり検証されたツール
- ほとんどのLinux/Unixシステムで同じ概念
- 設定文法がシンプルで例が豊富
- systemd以前のシステムでも使用可能
2.4 cronの限界
- サービスと分離されているため「どのサービスに関連するジョブか」を追跡しにくい
- 状態・ログ確認が不便(syslog、メールなどに分散)
- 依存関係管理(他のサービスが先に起動している必要がある等)が弱い
- 「起動後5分で一度だけ実行」など相対時間ベースのスケジューリングが曖昧
3. systemd timerの基本概念
3.1 systemd timerとは?
systemd timerはsystemdのタイマーユニット(.timer)です。
特定の条件(時間、起動後経過時間等)に応じて別のsystemdサービスを実行します。
つまり構造は常にペアで存在します。
myjob.service→ 実際に実行するタスクを定義myjob.timer→ いつ実行するかを定義
3.2 サービス + タイマーの基本例
毎朝3時にバックアップを実行する例をsystemd timerで書くと次のようになります。
(1) サービスユニット: /etc/systemd/system/backup.service
[Unit]
Description=Daily backup job
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
(2) タイマーユニット: /etc/systemd/system/backup.timer
[Unit]
Description=Run daily backup at 3:00
[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true
[Install]
WantedBy=timers.target
有効化:
sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer
3.3 systemd timerのメリット
- サービスと明確に結びつく: どのサービスがどのタイマーで実行されるか構造がはっきり
- ログ管理が容易:
journalctl -u backup.serviceなどでログを確認 - 柔軟なトリガー条件:
OnCalendar=: cronに似た時間ベースの表現OnBootSec=: 起動後X秒後OnUnitActiveSec=,OnUnitInactiveSec=など: 最後の実行後一定時間- 依存関係処理: 「ネットワークが起動した後にのみ実行」などをサービスの
After=network-online.target等で表現可能 - systemdエコシステムと統合:
systemctl list-timers,systemctl statusで状態確認
3.4 systemd timerのデメリット
cronに比べ学習曲線がある(サービス+タイマーの2ファイルが必要)- systemd環境に依存(古いシステムやnon-systemd環境では使用不可)
- 単純な1行ジョブには「やや過剰」に感じることがある
4. cron vs systemd timer: 機能比較
4.1 大まかな比較表
| 項目 | cron | systemd timer |
|---|---|---|
| 設定場所 | /etc/crontab, crontab -e |
/etc/systemd/system/*.service と /etc/systemd/system/*.timer |
| 実行対象 | 任意のコマンド/スクリプト | systemdサービス |
| 時間表現 | cron式(5フィールド) | OnCalendar, OnBootSec等多様 |
| 起動後X秒/分/時間 | @reboot+遅延(sleep等)で代用は可能だが、素直には書きにくい | OnBootSec, OnStartupSecで直接サポート |
| 失敗/再試行管理 | 別実装必要 | サービスユニット設定で一部可能 |
| ログ確認 | syslog、メール等 | journalctl -u <service> |
| 依存性(ネットワーク/ファイルシステム) | 基本サポートなし | Unitオプション(After=, Requires=等)で表現 |
| システム統合度 | 低い | 非常に高い(systemd全体と連携) |
| 移植性(他OSへ) | 比較的高い | systemdに依存 |
5. 例で見る違い
5.1 毎朝3時のバックアップ: cron vs timer
cron版
0 3 * * * /usr/local/bin/backup.sh
systemd timer版
# backup.service
[Unit]
Description=Daily backup job
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
# backup.timer
[Unit]
Description=Run daily backup at 3:00
[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true
[Install]
WantedBy=timers.target
5.2 起動後5分で一度だけ実行
cronでは@reboot + sleepやrc.localなどのトリックが必要です。
systemd timerで実装
# init-job.service
[Unit]
Description=Run custom init job after boot
[Service]
Type=oneshot
ExecStart=/usr/local/bin/init-job.sh
# init-job.timer
[Unit]
Description=Run init job 5 minutes after boot
[Timer]
OnBootSec=5min
AccuracySec=1min
[Install]
WantedBy=timers.target
これで、起動後5分経過するとinit-job.serviceが一度だけ実行されます。
6. どちらを選ぶべきか?
6.1 cronを継続して使うと良いケース
- 既に動作しているcronジョブが多く、systemd統合が必須でない場合
- 非常にシンプルな定期ジョブが数個だけある小規模サーバー
- systemd以外の環境(コンテナ、BSD、非常に古いOSなど)も考慮する場合
6.2 systemd timerを使うと良いケース
- 既にサービスがほとんどsystemdで管理されている場合
- ジョブ失敗時のログ/状態を一元管理したい場合
- 「起動後X時間後」や「最後の実行後Y時間後」など相対時間ベースのスケジューリングが必要な場合
- 特定サービス(例: DB、ネットワーク)が起動した後にのみ実行したいジョブがある場合
- CI/CDパイプライン、プロダクション環境などで一貫した管理/観測性が必要な場合
7. 既存cronジョブをsystemd timerへ移行する際のヒント
実際のマイグレーションは次の流れで考えると楽です。
- 現在のcronジョブ一覧を整理
*
crontab -l*/etc/crontab,/etc/cron.d/*を確認 - 各ジョブを「サービス + タイマー」に分解
* 「何を実行するか?」 →
.service* 「いつ実行するか?」 →.timer - 時間表現を変換
*
0 3 * * *→OnCalendar=*-*-* 03:00:00**/5 * * * *→OnCalendar=*:0/5(5分ごと等、複数表現が可能) - テスト
*
systemctl start myjob.serviceで手動実行を確認 *systemctl start myjob.timer→systemctl list-timersでスケジュール確認 - 既存cronを無効化 * 新しいタイマーが安定したら、該当cronエントリはコメントアウトまたは削除
8. まとめ:共存も可能
整理すると:
cronは依然として単純で移植性の高いスケジューラsystemd timerはモダンLinux環境でサービス中心の管理、観測性、柔軟なトリガーを提供する強力なツール
どちらか一方が「正解」というわけではありません。既存のcronジョブを無理に全部移行する必要はありませんが、新規に作成するスケジュールやサービスと強く結びつくジョブはsystemd timerを検討すると良いでしょう。

コメントはありません。