Systemd TimerとCron: 適切なスケジューラを選ぶ

cronとsystemdタイマーを比較し、単純なジョブ、サービス、ログ、依存関係に適したLinuxスケジューラを選択できるようにします。

Systemdタイマー vs. Cron:適切なスケジューラの選択

Linuxサーバーでバックアップ、クリーンアップ、ヘルスチェック、レポートを定期的に実行する必要がある場合、通常はcronとsystemdタイマーのどちらかを選択します。Cronは今でもシンプルで移植性が高いです。Systemdタイマーは、ジョブが管理されたサービスのように動作し、ログ、依存関係、リソース制御が必要な場合に適しています。

適切な選択は、実行するマシン、ジョブの障害動作、および必要な運用の可視性の程度によって異なります。

Cronジョブについて

cronは、Unix系オペレーティングシステムにおける時間ベースのジョブスケジューラです。ユーザーは、固定された時間、日付、または間隔で定期的にコマンドやスクリプトを実行するようにスケジュールできます。cronデーモン(crond)はバックグラウンドで実行され、crontabファイルにスケジュールされたジョブがないか確認します。

Cronの仕組み

各ユーザーは、crontabコマンドを使用して管理される独自のcrontabファイルを持つことができます。システム全体のジョブは、通常/etc/crontabまたは/etc/cron.d/内のファイルで設定されます。

crontabエントリは特定の形式に従います:

* * * * * command_to_execute
│ │ │ │ │
│ │ │ │ └───── 曜日 (0 - 6) (日曜日=0または7)
│ │ │ └─────── 月 (1 - 12)
│ │ └───────── 日 (1 - 31)
│ └─────────── 時 (0 - 23)
└───────────── 分 (0 - 59)

例: 毎日午前2:00にバックアップスクリプトを実行する場合:

0 2 * * * /usr/local/bin/backup.sh

Cronの利点

  • 普遍性: 事実上すべてのUnix系システムで利用可能。
  • シンプルな構文: crontab形式は、基本的なスケジューリングに関しては比較的学習が容易。
  • ユーザー固有のジョブ: 個々のユーザー向けにジョブを簡単に設定可能。

Cronの欠点

  • 柔軟性の制限: 主に固定された時間間隔に基づく。複雑な依存関係やイベント駆動型のスケジューリングの処理は困難。
  • 依存関係管理なし: あるジョブが別のジョブの正常完了後にのみ実行されるべきである、といったことを簡単に定義できない。
  • リソース制御なし: スケジュールされたジョブが消費するリソース(CPU、メモリ)をほとんど制御できない。
  • ログ記録と監視: 多くの場合、メール出力、syslog、またはコマンド内での明示的なリダイレクトに依存する。
  • ユニットファイル統合: systemdのサービス管理機能と直接統合されていない。

Systemdタイマーについて

systemdタイマーは、systemdのユニットファイルの力を活用した、より高度で柔軟なタスクスケジューリング方法です。別個のデーモンではなく、systemdタイマーはsystemd initシステム自体の一部として管理されます。

Systemdタイマーの仕組み

systemdタイマーは、2つのユニットファイルで構成されます:

  1. サービスユニット(.service): 実行するタスクまたはコマンドを定義します。
  2. タイマーユニット(.timer): 対応するサービスユニットをいつアクティブにするかを定義します。

これらのファイルは通常、/etc/systemd/system/または~/.config/systemd/user/に配置されます。

例: クリーンアップスクリプトを毎日午前3:00に実行するようにスケジュールします。

まず、サービスファイル(cleanup.service)を作成します:

# /etc/systemd/system/cleanup.service

[Unit]
Description=毎日のクリーンアップタスク

[Service]
Type=oneshot
ExecStart=/usr/local/bin/cleanup.sh

次に、タイマーファイル(cleanup.timer)を作成します:

# /etc/systemd/system/cleanup.timer

[Unit]
Description=クリーンアップタスクを毎日実行

[Timer]
# 起動から25分後、その後毎日午前3時に実行
OnBootSec=25min
OnCalendar=*-*-* 03:00:00
# 代替:前回の実行から24時間後に実行
# OnUnitActiveSec=24h

[Install]
WantedBy=timers.target

これらのファイルを作成した後、systemdをリロードし、将来の起動のためにタイマーを有効にして、今すぐ起動します:

sudo systemctl daemon-reload
sudo systemctl enable cleanup.timer
sudo systemctl start cleanup.timer

タイマーのステータスと次にトリガーされる時刻は、以下を使用して確認できます:

sudo systemctl status cleanup.timer

主要なsystemdタイマーディレクティブ:

  • OnCalendar=:カレンダーイベント時刻を指定します(cronの構文に似ていますが、より強力です)。
    • *-*-* 03:00:00:毎日午前3時。
    • Mon..Fri *-*-* 09:00:00:平日の午前9時。
    • hourly:毎時。
    • daily:1日1回。
    • weekly:週1回。
    • monthly:月1回。
    • yearly:年1回。
  • OnBootSec=:システム起動から指定された時間後にトリガーします。
  • OnUnitActiveSec=:対応するユニット(サービス)が最後にアクティブ化されてから指定された時間後にトリガーします。
  • OnUnitInactiveSec=:対応するユニット(サービス)が非アクティブになってから指定された時間後にトリガーします。
  • AccuracySec=:タイマーが必要とする精度。値を低くすると、より多くの電力を消費する可能性があります。
  • Persistent=:カレンダータイマーの場合、trueに設定すると、マシンの電源がオフになっているなど、タイマーが非アクティブな間にスケジュールされた実行が missed された場合に、systemdに追いつくように指示します。

Systemdタイマーの利点

  • systemdとの統合: systemdのサービス管理、ログ記録(journalctl)、リソース制御、依存関係管理とシームレスに統合。
  • 柔軟性: 固定間隔以外にも、カレンダーイベント、起動後の相対時間、前回のアクティブ化からの相対時間など、さまざまなスケジューリングオプションをサポート。
  • 依存関係管理: 他のsystemdユニット(例:ネットワーク可用性)への依存関係を定義可能。
  • リソース制御: リソース制限(CPU、メモリ)のためにsystemdのcgroupsを活用可能。
  • ログ記録: 包括的で集中管理されたログ記録のためにjournaldと統合。
  • エラー処理: Restart=OnFailure=、およびそれらのパターンがジョブに適合する場合の依存関係順序付けなどのサービスユニット動作を使用可能。
  • 状態認識: ジョブが実行されるはずだった時刻を追跡し、Persistent=trueが設定されている場合、システム起動時にそれを実行可能。

Systemdタイマーの欠点

  • 学習曲線が急: systemdユニットファイルの構文と概念は、初心者にとってcronよりも複雑な場合がある。
  • Systemd依存: systemdを実行しているシステムが必要(ほとんどの最新のLinuxディストリビューションは実行している)。

Systemdタイマー vs. Cron:主な違いのまとめ

機能 Cronジョブ Systemdタイマー
管理 crontabコマンド、システムファイル systemctlコマンド、ユニットファイル
スケジューリング 固定の分、時、日、月、曜日 カレンダーイベント、相対時間、起動ベース
統合 スタンドアロンデーモン systemdと統合
ログ記録 メール、スクリプトリダイレクト journald
依存関係 なし systemdユニット依存関係
リソース制御 なし systemd cgroups
エラー処理 基本 サービスユニット障害処理
状態追跡 制限あり Persistent=オプション
複雑さ 基本的なタスクにはよりシンプル より強力、学習曲線は急

どのスケジューラを選ぶべきか

Cronを選ぶ場合:

  • systemdを使用していない非常に古い、または最小限のシステムを使用している場合。
  • 固定された定期的なスケジュールで非常に単純な単発タスクをスケジュールする必要があり、高度な機能よりもシンプルさを優先する場合。
  • 独自のログ記録とエラー処理を既に行っているコマンドのクイックスケジュールが必要な場合。

Systemdタイマーを選ぶ場合:

  • systemdを使用する最新のLinuxディストリビューションを使用している場合。
  • ジョブが実行されるタイミングをより細かく制御する必要がある場合(例:起動時、前回の実行時、ネットワーク起動後など)。
  • より優れたログ記録、監視、エラー処理が必要な場合。
  • リソース制御や依存関係管理を含む、systemdの強力なサービス管理機能を使用してジョブ実行を管理したい場合。
  • すでに他のサービスをsystemdで管理しており、スケジューリングに一貫したアプローチを採用したい場合。
  • タスクに他のシステムサービスやイベントへの依存関係がある場合。

実用的な経験則

ジョブが短く明白なコマンドであり、移植性が重要な場合はcronを使用します。ジョブがサービスの一部である場合、journalctlログが必要な場合、ネットワークを待つ必要がある場合、またはリソース制限や依存関係の順序付けが有益な場合は、systemdタイマーを使用します。

夜間バックアップは良い例です。小さなレガシーサーバーでは、0 2 * * * /usr/local/bin/backup.shで十分かもしれません。systemdベースの本番ホストでは、backup.servicebackup.timerを組み合わせることで、より明確なステータス、ログ、Persistent=trueによる起動時のキャッチアップ、そして後で依存関係を追加するためのよりクリーンなパスが得られます。