Systemdタイマーユニットの作成と管理方法
実用的な`.timer`、`.service`、`systemctl`、`journalctl`の例を使って、systemdタイマーユニットの作成、有効化、監視、トラブルシューティングを行います。
Systemdタイマーユニットの作成と管理方法
Systemdタイマーユニットは、cronに依存せずにLinuxでジョブをスケジュールします。サーバーでバックアップ、クリーンアップジョブ、ヘルスチェック、レポートを予定された時間に実行する必要がある場合、systemdタイマーはスケジューリング、サービス分離、依存関係処理、ログを一箇所で提供します。
重要な考え方はシンプルです。.timerファイルは実行タイミングを指定し、.serviceファイルは実行内容を指定します。この分割により、タイマーはsystemctlで簡単に検査でき、journalctlで簡単にデバッグできます。
Systemdタイマーユニットの構造を理解する
systemdタイマーユニットは常に、アクティブ化する対象となる対応するサービスユニット(または他のユニットタイプ)とペアになります。タイマーユニット自体は、関連するユニットをいつアクティブ化するかを定義し、サービスユニットは何を実行するかを定義します。両方のユニットは通常、同じディレクトリ(カスタムユニットの場合は多くの場合/etc/systemd/system/)に配置されます。
典型的なタイマーユニットファイルは.timer拡張子を持ち、関連するサービスユニットファイルは.service拡張子を持ちます。たとえば、mytask.serviceで定義されたタスクをスケジュールする場合は、mytask.timerファイルを作成します。
例: mytask.timer
[Unit]
Description=カスタムタスクを毎日実行
[Timer]
OnCalendar=daily
Persistent=true
[Install]
WantedBy=timers.target
主要なセクションを詳しく見てみましょう。
[Unit]セクション:Description: タイマーの人間が読める説明。ステータス出力での識別に役立ちます。
[Timer]セクション: タイマーユニットの核であり、スケジューリングを定義します。OnCalendar=daily: このディレクティブは、タイマーをアクティブ化するタイミングを指定します。dailyは毎日深夜0時の省略形です。他の例としては次のものがあります。hourly: 毎時。weekly: 毎週(Mon *-*-* 00:00:00と同等)。Sun *-*-* 10:00: 毎週日曜日の午前10時。*-*-15 14:30: 毎月15日の午後2時30分。Mon..Fri *-*-* 09:00: 平日の午前9時。
Persistent=true: これがtrueに設定されている場合、システムがオフの間にイベントが発生した場合、タイマーは可能な限り早くアクティブ化されます。OnCalendarタイマーの場合、システムがスケジュールされた時間にオフだった場合、タイマーはシステムが起動してタイマーがアクティブになるとすぐにトリガーされます。OnBootSec=: システム起動から指定された時間後にタイマーをアクティブ化します。たとえば、OnBootSec=15minは起動後15分でトリガーされます。OnUnitActiveSec=: アクティブ化するユニットが最後にアクティブになってから指定された時間後にタイマーをアクティブ化します。たとえば、OnUnitActiveSec=1hは、関連するサービスが最後にアクティブ化されてから1時間後に別の実行をスケジュールします。OnUnitInactiveSec=: アクティブ化するユニットが最後に非アクティブになってから指定された時間後にタイマーをアクティブ化します。AccuracySec=: タイマーの精度を指定します。Systemdは、イベントがこの時間枠内にある場合にのみ、タイマーのためにシステムを起動しようとし、電力節約に役立ちます。デフォルトは1minです。RandomizedDelaySec=: タイマートリガーにランダムな遅延を追加します(指定された期間まで)。負荷分散に役立ちます。
[Install]セクション: このセクションは、タイマーユニットを有効にする方法を定義します。WantedBy=timers.target: このディレクティブは、タイマーが有効になると、アクティブなすべてのタイマーを含む標準ターゲットであるtimers.targetの一部になるようにします。つまり、タイマーは有効になると起動時に自動的に開始されます。
例: mytask.service
[Unit]
Description=マイカスタムタスクサービス
[Service]
Type=oneshot
ExecStart=/usr/local/bin/my_custom_script.sh
User=myuser
Group=mygroup
[Install]
WantedBy=multi-user.target
[Unit]セクション:Description: サービスの説明。
[Service]セクション: サービス自体を定義します。Type=oneshot: 1回実行して終了するタスクに適しています。長時間実行されるデーモンには他のタイプが存在します。ExecStart: 実行するコマンド。スクリプトに実行権限があることを確認してください。User/Group: コマンドを実行するユーザーとグループを指定します。絶対に必要な場合を除き、タスクをrootとして実行しないことをお勧めします。
[Install]セクション: このセクションは、タイマーによってのみ開始されるべきワンショットサービスには通常必要ありません。サービスではなく、タイマーを有効にします。
タイマーユニットの作成と有効化
以下の手順に従って、systemdタイマーユニットを作成および管理します。
サービスユニットファイルを作成する:
.serviceファイルでタスクを定義します。/etc/systemd/system/(またはユーザー固有のタイマーの場合は~/.config/systemd/user/)に配置します。sudo nano /etc/systemd/system/mytask.service上記のサンプルサービスコンテンツを貼り付けて保存します。
タイマーユニットファイルを作成する: 対応する
.timerファイルでスケジュールを定義します。サービスファイルと同じディレクトリに配置します。sudo nano /etc/systemd/system/mytask.timer上記のサンプルタイマーコンテンツを貼り付けて保存します。
Systemdデーモンをリロードする: ユニットファイルを作成または変更した後、systemdに設定をリロードするように指示する必要があります。
sudo systemctl daemon-reloadタイマーを有効にする: タイマーを起動時に自動的に開始させるには、有効にします。
sudo systemctl enable mytask.timer注: サービスファイルがタイマーによってのみトリガーされることを目的としている場合は、有効にしないでください。
タイマーを開始する: タイマーをすぐに開始します。その後、スケジュールに従って実行されます。
sudo systemctl start mytask.timer
タイマーユニットの管理と監視
Systemdは、タイマーを管理および監視するためのいくつかのsystemctlコマンドを提供します。
すべてのタイマーを一覧表示する: アクティブおよび非アクティブなすべてのタイマーを表示します。
systemctl list-timersこのコマンドは次のような出力を提供します。
NEXT LEFT LAST PASSED UNIT ACTIVATES Tue 2023-10-27 08:00:00 UTC 10h left Wed 2023-10-26 08:00:00 UTC 14h ago mytask.timer mytask.serviceこれは、タイマーが次に実行される予定の時刻、実行までの残り時間、最後に実行された時刻、およびアクティブ化するサービスを示します。
特定のユニットのタイマーを一覧表示する: 特定のサービスに関連するタイマーを表示する場合。
systemctl list-timers --all | grep mytask.serviceタイマーのステータスを確認する: 特定のタイマーに関する詳細情報を取得します。
systemctl status mytask.timerこれにより、タイマーがアクティブかどうか、次に実行される予定時刻、および最近のログエントリが表示されます。
サービスのログを表示する: タイマーによって実行されたタスクの出力とステータスを確認するには、関連するサービスのログを確認します。
journalctl -u mytask.serviceログをリアルタイムで追跡することもできます。
journalctl -f -u mytask.serviceタイマーを停止する: タイマーを一時的に無効にする必要がある場合。
sudo systemctl stop mytask.timerタイマーを無効にする: タイマーが起動時に開始されないようにし、実行中の場合は停止します。
sudo systemctl disable --now mytask.timer
高度なタイマー設定
特定の間隔の設定
dailyやhourlyの代わりに、より正確な間隔を定義できます。
- N分ごと:
OnUnitActiveSec=15min(サービスが最後にアクティブ化されてから15分後に実行)。 - 特定の時間:
OnCalendar=*-*-* 02:30:00(毎日午前2時30分に実行)。 - 条件の組み合わせ:
OnCalendar=Mon..Fri *-*-* 08:00:00(平日の午前8時に実行)。
省電力のためのAccuracySecの使用
タスクを正確な瞬間に実行する必要がない場合は、AccuracySecの使用を検討してください。たとえば、AccuracySec=5minは、スケジュールされた時間から5分以内にシステムを起動しても問題ないことをsystemdに伝えます。これにより、systemdはタイマーイベントをバンドルし、システムをより長く低電力状態に保つことができます。
[Timer]
OnCalendar=hourly
AccuracySec=5min
PersistentとWakeSystem
Persistent=trueは、システムがオフのためにOnCalendarイベントが見逃された場合、次の起動時に1回実行されるようにします。これは、スキップしてはならないタスクにとって重要です。WakeSystem=trueは、システムとハードウェアがサポートしている場合、タイマーのためにシステムをサスペンドから復帰させるようsystemdに要求します。これは、マシンがAC電源かバッテリーかを決定するのと同じではありません。
タイマーとCronの比較
| 機能 | Systemdタイマー | Cron |
|---|---|---|
| 統合 | systemdサービス、ターゲットとの深い統合 | スタンドアロンユーティリティ |
| スケジューリング | 柔軟(カレンダー、相対、起動ベース) | 主に時間ベースの式 |
| ログ記録 | journalctlを介して一元化 |
分散(/var/log/syslog、/var/log/cron.log) |
| エラー処理 | アクションをサービス障害に結び付けることが可能 | 基本的なメール通知 |
| 依存関係 | 他のサービスがアクティブであることに依存可能 | 制限あり |
| 実行 | 特定のユーザー、グループとして実行可能 | crontabを介して特定のユーザーとして実行可能 |
| 電力管理 | 省電力向けに最適化可能(AccuracySec) |
直接的な制御は少ない |
Systemdタイマーを選択する場合:
- 他のsystemdサービスとのより緊密な統合が必要な場合。
- 一元化されたログ記録とより簡単なデバッグが優先事項である場合。
- より高度なスケジューリングオプション(例:前回の実行からの経過時間)が必要な場合。
- システム状態や電力管理に関連するタスクの場合。
Cronが依然として好まれる場合:
- systemdを完全に採用していないシステムでの非常に単純なスタンドアロンタスクの場合。
- さまざまなLinuxディストリビューションおよび古いシステム間での最大の互換性を確保するため。
一般的な問題のトラブルシューティング
- タスクが実行されない:
- タイマーのステータスを確認する:
systemctl status mytask.timer。Active: activeおよびTriggered...メッセージを探します。 - サービスのログを確認する:
journalctl -u mytask.service。スクリプトが実行可能で、エラーがないことを確認します。 OnCalendarの構文を確認する:systemd-analyze calendar 'your-calendar-string'を使用してテストします。- タイマーが有効化され、開始されていることを確認する:
systemctl list-timers --all。
- タイマーのステータスを確認する:
- タスクが早すぎる/遅すぎる:
AccuracySecとRandomizedDelaySecを確認します。- システムクロックが正確であることを確認します(
timedatectl status)。
- 権限エラー:
.serviceファイルで指定されたUserとGroupが、スクリプトおよびアクセスするファイルに対して必要な権限を持っていることを確認します。- ユーザーが指定されていない場合、デフォルトでrootになります。root権限には注意してください。
まとめ
ジョブがマシンのサービスレイヤーに属する場合、つまりバックアップ、クリーンアップタスク、監視チェック、証明書更新フック、その他の運用作業には、systemdタイマーを使用します。最初にサービスを作成し、次にタイマーを作成し、systemctl daemon-reloadを実行し、タイマーを有効にして開始し、systemctl list-timers --allとjournalctl -u your.serviceで確認します。