systemd timer と cron の使い分け
どちらを使うべきか?
迷ったら systemd timer を選ぶのが現代 Linux の基本方針。ジョブの実行ログが journalctl に統合され、依存関係制御・失敗時の再試行・実行漏れ補完も設定できる。ただし、既存の cron ジョブを維持する場合や、1 行で書ける単純なジョブは cron のままでも問題ない。
選択の目安
| 用途 | 推奨 |
|---|---|
| 新規で定期実行を実装 | systemd timer |
| journalctl でログを一元管理したい | systemd timer |
| 実行条件・依存関係を設定したい | systemd timer |
| 起動後の遅延実行が必要 | systemd timer |
| 既存 cron ジョブの維持 | cron のまま |
| シンプルな 1 行スクリプト | cron |
cron とは何か?
cron は UNIX 伝統のジョブスケジューラで、テキスト 1 行で定期実行を設定できる。設定は crontab コマンドで管理し、分・時・日・月・曜日の 5 フィールドで実行タイミングを指定する。
crontab の基本書式
分 時 日 月 曜日 コマンド
# 毎日 3:00 にバックアップスクリプトを実行 0 3 * * * /home/user/scripts/backup.sh # 5 分ごとにログを収集 */5 * * * * /usr/local/bin/collect-logs.sh # 毎週月曜 9:00 にレポート送信 0 9 * * 1 /usr/local/bin/send-report.sh
crontab の操作コマンド
# 現在のユーザーの crontab を編集 crontab -e # crontab の内容を表示 crontab -l # crontab を削除(全ジョブが消えるので注意) crontab -r
cron はデフォルトでジョブの成否をメールで通知する。メール設定がない環境では /var/spool/mail に出力が蓄積されるため、不要なら crontab 先頭に MAILTO="" を追加する。
systemd timer とは何か?
systemd timer は、.timer ファイル(スケジュール定義)と .service ファイル(実行内容)の 2 ファイルで構成する定期実行の仕組み。両方を systemd が管理するため、ログ・依存関係・状態確認が統一インターフェースで行える。
最小構成の例(5 分ごとに実行)
/etc/systemd/system/collect-logs.service
[Unit]
Description=Collect system logs
[Service]
Type=oneshot
ExecStart=/usr/local/bin/collect-logs.sh
/etc/systemd/system/collect-logs.timer
[Unit]
Description=Run collect-logs every 5 minutes
[Timer]
OnCalendar=*:0/5
Persistent=true
[Install]
WantedBy=timers.target
timer の有効化と状態確認
# ユニットファイルの変更を systemd に反映 sudo systemctl daemon-reload # timer を有効化して即座に起動 sudo systemctl enable --now collect-logs.timer # 動作中の timer 一覧と次回実行時刻を確認 systemctl list-timers # サービスの実行ログを確認 journalctl -u collect-logs.service
systemd timer が優れる点は何か?
cron と比較したときの主な利点は ログの一元管理 と 細かい実行制御 の 2 点に集約できる。
ログが journalctl に統合される
# 直近 50 件の実行ログを確認 journalctl -u collect-logs.service -n 50 # 今日の実行ログだけ表示 journalctl -u collect-logs.service --since today # エラーのみ表示 journalctl -u collect-logs.service -p err
cron のジョブ出力はメールやファイルに分散するが、systemd timer は journalctl で全サービスのログと一元的に調査できる。障害時に時系列を追う際の手間が大幅に減る。
サービス依存関係を設定できる
[Unit]
Description=Database backup
Requires=postgresql.service
After=postgresql.service
PostgreSQL などの特定サービスが起動している場合のみ実行する、という条件を設定できる。cron にはこの仕組みがなく、スクリプト内で手動チェックが必要になる。
起動後の遅延実行が可能
[Timer]
# 起動後 10 分経過してから最初に実行
OnBootSec=10min
# その後 1 時間ごとに繰り返す
OnUnitActiveSec=1h
OnCalendar による絶対スケジュールと、OnBootSec/OnUnitActiveSec による相対スケジュールの 2 種類を使い分けられる。
Persistent=true で実行漏れを補完する
[Timer]
OnCalendar=daily
Persistent=true
Persistent=true を設定すると、サーバがダウンしていた期間にスキップされたジョブを次回起動時に補完実行する。cron ではこの動作は標準では得られない(別途 anacron が必要)。
OnCalendar の書式はどう書くのか?
OnCalendar は systemd 独自の日時書式を使用する。有効化前に systemd-analyze calendar で構文を検証するのが基本手順。
# 書式を検証し、次の実行時刻を表示 systemd-analyze calendar "Mon *-*-* 03:00:00" # よく使うパターン OnCalendar=daily # 毎日 00:00 OnCalendar=hourly # 毎時 00:00 OnCalendar=weekly # 毎週月曜 00:00 OnCalendar=*:0/5 # 5 分ごと OnCalendar=Mon 03:00 # 毎週月曜 3:00 OnCalendar=*-*-* 03:00:00 # 毎日 3:00(上と同じ)
systemd-analyze calendar は timer を有効化する前の必須確認コマンド。次回と次々回の実行予定時刻も表示されるため、タイポや意図しないスケジュールをすぐ発見できる。
cron を systemd timer に移行するには?
既存の cron ジョブを systemd timer に移行する手順をステップごとに示す。
ステップ 1:既存 cron ジョブを確認
crontab -l # 0 3 * * * /home/user/scripts/backup.sh
ステップ 2:.service ファイルを作成
sudo nano /etc/systemd/system/backup.service
[Unit]
Description=Daily backup
[Service]
Type=oneshot
User=user
ExecStart=/home/user/scripts/backup.sh
ステップ 3:.timer ファイルを作成
sudo nano /etc/systemd/system/backup.timer
[Unit]
Description=Run backup daily at 3:00
[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true
[Install]
WantedBy=timers.target
ステップ 4:有効化して動作確認
sudo systemctl daemon-reload sudo systemctl enable --now backup.timer # timer が登録されたことを確認 systemctl list-timers --all | grep backup # 実行後にログを確認 journalctl -u backup.service --since today
ステップ 5:cron ジョブを無効化
crontab -e # 移行済みの行を削除またはコメントアウト
移行後は systemctl list-timers と journalctl -u backup.service で実際に動作することを確認してから cron ジョブを削除する。両方を残しておくと二重実行になる。
比較まとめ
| 項目 | cron | systemd timer |
|---|---|---|
| 設定の手軽さ | 1 行で書ける | .timer + .service の 2 ファイル |
| ログ確認 | メール or ファイル | journalctl |
| 依存関係設定 | 不可 | 可能 |
| 起動遅延実行 | 不可 | 可能(OnBootSec) |
| 実行漏れ補完 | 不可(anacron は別) | Persistent=true |
| ユーザー権限 | 各ユーザーの crontab | ユーザーサービスも対応 |
| 確認コマンド | crontab -l |
systemctl list-timers |