Systemdでのタイマーの使用

systemdタイマー・ユニットのスケジュールの仕組みと、リアルタイム・タイマー、モノトニック・タイマーおよび一時タイマーの構成方法について説明します。

タイマー・ユニット・ファイルは、systemctlユーティリティでタスクのスケジューリングに使用されるsystemdファイルの一種です。このユーティリティはcronユーティリティに似ており、cronユーティリティでは、同じ目的のためにcrontabおよびその他のcronジョブが使用されます。

cronデーモンはsystemd内のサービスとして実行されるため、タイマー・ユニットは追加された処理のレイヤーを削除し、cronサービスで使用可能なものよりはるかに多くのユーティリティおよびより詳細な構成を提供するため、推奨されます。

一般に、パッケージでシステムで機能する特定のサービスが使用される場合、そのパッケージには、それ固有のsystemdタイマー・ユニット・ファイルが含まれています。そのため、これらのパッケージをOracle Linuxとともにインストールすると、そのタイマー・ユニット・ファイルが自動的に含まれます。次のコマンドを使用すると、システム上のタイマー・ファイルを表示できます。

systemctl list-unit-files --type=timer
ノート

タイマー・ファイルのリストは、Oracle Linuxが実行されている場所(Oracle Cloud Infrastructureにあるインスタンス、物理システムなど)によって異なる場合があります。

各タイマー・ユニット・ファイルには、タスクのスケジュールを管理するパラメータ設定が含まれています。たとえば、dnf-makecache.serviceを実行するスケジュールは、dnf-makecache.timerファイル内で設定されます。このファイルには、次のような設定が含まれています。

systemctl cat dnf-makecache.timer
# /usr/lib/systemd/system/dnf-makecache.timer
[Unit]
Description=dnf makecache --timer
ConditionKernelCommandLine=!rd.live.image
# See comment in dnf-makecache.service
ConditionPathExists=!/run/ostree-booted
Wants=network-online.target

[Timer]
OnBootSec=10min
OnUnitInactiveSec=1h
RandomizedDelaySec=60m
Unit=dnf-makecache.service

[Install]
WantedBy=timers.target

スケジュール情報は、[Timer]セクションで指定します。

この構成例では、dnf-makecache.serviceサービスが、システムがブートされた10分後に自動実行されるように設定されています。このサービスは、その後、OnUnitInactiveSecパラメータで指定されているとおり、1時間の間、アイドル・モードになります。この時間が終了すると、このサービスが再度実行されます。このサイクルは無期限に続き、1時間ごとに起こります。

RandomizedDelaySec設定では、実行をそのスケジュールよりどのくらい遅らせることができるかの上限値を指定します。

この例では、このサービスの実行は、遅くともそのスケジュールの1分後まで許可されています。このパラメータは、指定したスケジュールで同時に開始されるジョブが多くなりすぎないようにするために役立ちます。そのようにしないと、リソースが過負荷になる可能性があります。

OnCalendarも、タスク・スケジューリングのための有用なパラメータです。このパラメータが次のように設定されているとします。

OnCalendar=*:00/10

*:00により毎正時を、/10という設定により10分を表しています。したがって、このジョブは、毎正時の10分後に、1時間ごとに実行されるように設定されます。

ジョブのスケジューリングのためのsystemdタイマー・ユニット・ファイルのパラメータをすべて示するリストは、systemd.timer(5)のマニュアル・ページを参照してください。

ヒント

systemdタイマー・ユニット・ファイルの構成方法など、Oracle Linuxでのsystemdの使用方法に関するチュートリアルでは、https://docs.oracle.com/en/learn/ol-systemd/を参照してください。

タイマー・ユニットを使用したサービス・ユニット・ランタイムの制御

タイマー・ユニットがcronジョブをどのように置き換えるか、およびタイマー・トリガー・サービスを検査、有効化およびモニターする方法について説明します。

タイマー・ユニットは、サービス・ユニットの実行時期を制御するように構成できます。

時間ベースのイベント用にcronデーモンを構成するかわりに、タイマー・ユニットを使用できます。タイマー・ユニットは、crontabエントリを作成するよりも構成が複雑になる場合があります。ただし、タイマー・ユニットはより構成しやすく、制御するサービスは、ロギングを改善したりsystemdアーキテクチャとより深く統合するように構成できます。

タイマー・ユニットは、サービス・ユニットと同様に開始、有効化および停止されます。たとえば、タイマー・ユニットをすぐに有効にして開始するには、次のように入力します:

sudo systemctl enable --now myscript.timer

システム上の既存のすべてのタイマーを一覧表示し、最終実行日時、および次回実行するように構成する日時を確認するには、次のように入力します:

systemctl list-timers

システム・タイマーの詳細は、systemd.timer(5)およびsystemd.time(7)のマニュアル・ページを参照してください。

リアルタイム・タイマー・ユニットの構成

リアルタイム・タイマーは、crontab内のイベントと同様に、カレンダ・イベントでアクティブ化します。オプションOnCalendarは、タイマーがサービスを実行する日時を指定します。

  • 必要に応じて、タイマー・ユニットによってトリガーされるサービスを定義する.serviceファイルを作成します。次の手順では、サンプル・サービスは、更新スクリプトを実行するサービス・ユニットである/etc/systemd/system/update.serviceです。

    サービス・ユニットの作成の詳細は、「ユーザーベースのsystemdサービスの作成」を参照してください。

  • サービスを実行する時間と頻度を決定します。この手順では、タイマーは月曜日から金曜日まで2時間ごとにサービスを実行するように構成されています。

このタスクでは、カレンダ・イベントに基づいて実行するサービスをトリガーするシステム・タイマーを作成する方法を示します。カレンダ・イベントの定義は、cronジョブに入れるエントリと似ています。

  1. 次の内容で/etc/systemd/system/update.timerを作成します:
    [Unit]
    Description="Run the update.service every two hours from Mon to Fri."
    
    [Timer]
    OnCalendar=Mon..Fri 00/2 
    Unit=update.service
    
    [Install]
    WantedBy=multi-user.target

    OnCalendarでは、OnCalendar=weeklyなどの簡単な設定を使用することも、より詳細な複雑な定義を使用することもできます。ただし、設定を定義する形式は、次のように一定です:

    DayofWeek Year-Month-Day Hour:Minute:Second

    次の定義は、"毎月最初の4日間の正午で、月曜日または火曜日"を意味します。

    OnCalendar=Mon,Tue *-*-01..04 12:00:00

    OnCalendarを定義するその他の方法、およびシステム・タイマー・ファイルで構成できる他のタイマー・オプションについては、systemd.timer(5)およびsystemd.time(7)のマニュアル・ページをご覧ください。

  2. このタイマーに関連するすべてのファイルが正しく構成されていることを確認します。
    systemd-analyze verify /etc/systemd/system/update.*

    検出されたエラーは画面に報告されます。

  3. タイマーを開始します。
    sudo systemctl start update.timer

    このコマンドは、現在のセッションのみのタイマーを開始します。

  4. システムのブート時にタイマーが開始されていることを確認します。
    sudo systemctl enable update.timer

モノトニック・タイマー・ユニットの構成

モノトニック・タイマーは、ブート・イベントなどの様々な開始ポイントに対して相対的なタイム・スパンの後にアクティブ化するか、特定のsystemdユニットはアクティブになるときにアクティブにします。これらのタイマー・ユニットは、コンピュータが一時的に中断またはシャットダウンされると停止します。モノトニック・タイマーは、OnTypeSecオプションを使用して構成します。ここで、Typeはタイマーが関連しているイベントの名前です。一般的なモノトニック・タイマーにはOnBootSecおよびOnUnitActiveSecが含まれます。

  • 必要に応じて、タイマー・ユニットによってトリガーされるサービスを定義する.serviceファイルを作成します。次の手順では、サンプル・サービスは、更新スクリプトを実行するサービス・ユニットである/etc/systemd/system/update.serviceです。

    サービス・ユニットの作成の詳細は、「ユーザーベースのsystemdサービスの作成」を参照してください。

  • サービスを実行する時間と頻度を決定します。この手順では、タイマーは、システムのブートして10分後、およびサービスが最後にアクティブ化された2時間ごとにサービスを実行するように構成されます。

このタスクでは、特定のイベント(システムのブート時またはタイマーのアクティブ化から2時間経過した後)で実行するサービスをトリガーするシステム・タイマーを作成する方法を示します。

  1. 次の内容で/etc/systemd/system/update.timerを作成します:
    [Unit]
    Description="Run the update.service every two hours from Mon to Fri."
    
    [Timer]
    OnBootSec=10min
    OnUnitActiveSec=2h
    Unit=update.service
    
    [Install]
    WantedBy=multi-user.target

    システム・タイマーで構成できるタイマー・オプションの詳細は、systemd.timer(5)およびsystemd.time(7)のマニュアル・ページに関する項を参照してください。

  2. このタイマーに関連するすべてのファイルが正しく構成されていることを確認します。
    systemd-analyze verify /etc/systemd/system/update.*

    検出されたエラーは画面に報告されます。

  3. タイマーを開始します。
    sudo systemctl start update.timer

    このコマンドは、現在のセッションのみのタイマーを開始します。

  4. システムのブート時にタイマーが開始されていることを確認します。
    sudo systemctl enable update.timer

一時タイマー・ユニットの実行

ユニット・ファイルを作成せずにad hocタスクをスケジュールできるように、systemctl runを使用してワンオフ・タイマーを起動する方法を示します。

一時タイマーは、現在のセッションでのみ有効な一時タイマーです。

これらのタイマーは、サービスまたはタイマー・ユニットをsystemd内に構成することなく、プログラムまたはスクリプトを直接実行するために作成できます。これらのユニットは、systemd-runコマンドを使用して生成されます。詳細は、systemd-run(1)マニュアル・ページを参照してください。

unit-file.timerファイルに追加するパラメータ・オプションは、systemd-runコマンドを使用して一時タイマー・ユニットを実行するときに引数としても機能します。

次の例は、systemd-runを使用して一時タイマーをアクティブ化する方法を示しています。

  • 2時間の経過後にupdate.serviceを実行します。

    sudo systemd-run --on-active="2h" --unit update.service
  • 1時間後に~/tmp/myfileを作成します。

    sudo systemd-run --on-active="1h" /bin/touch ~/tmp/myfile
  • サービス・マネージャの起動の5分後に~/myscripts/update.shを実行します。この構文を使用して、サービス・マネージャがユーザー・ログイン時に起動した後にサービスを実行します。

    sudo systemd-run --on-startup="5m" ~/myscripts/update.sh
  • システム・ブートの10分後にmyjob.serviceを実行します。

    sudo systemd-run --on-boot="10m" --unit myjob.service
  • 1日の終わりにreport.serviceを実行します。

    sudo systemd-run --on-calendar="17:00:00"