systemdユニットとユニットファイルの理解
紹介
Linuxディストリビューションはますますsystemd初期化システムを採用しています。この強力なソフトウェアスイートは、サービスからマウントされたデバイス、システム状態まで、サーバーの多くの側面を管理することができます。
systemdでは、unitはシステムが操作および管理する方法を知っている任意のリソースを指します。これは、systemdツールが扱う方法を知っている主要なオブジェクトです。これらのリソースは、ユニットファイルと呼ばれる設定ファイルを使用して定義されます。
このガイドでは、systemd が処理できるさまざまなユニットを紹介します。また、システムでこれらのリソースの扱い方を形作るためにユニットファイルで使用できる多くのディレクティブの一部についても説明します。
Systemdユニットは何を提供しますか?
ユニットは、systemd が管理できるオブジェクトです。これらは基本的に、デーモンのスイートによって管理されたり、提供されたユーティリティによって操作されたりできるシステムリソースの標準化された表現です。
ユニットは他のinitシステムのサービスやジョブに似ていると言えるかもしれません。しかし、ユニットはこれらを抽象化するために使用できるため、はるかに広範な定義を持っています。これには、サービス、ネットワークリソース、デバイス、ファイルシステムのマウント、および分離されたリソースプールが含まれます。
他の初期化システムでは1つの統一されたサービス定義で処理される可能性があるアイデアを、その焦点に応じてコンポーネントユニットに分けることができます。これにより機能ごとに整理され、ユニットのコア動作を変更することなく、機能の有効化、無効化、または拡張を簡単に行うことができます。
ユニットが簡単に実装できるいくつかの機能は次のとおりです:
- ソケットベースのアクティベーション: サービスに関連付けられたソケットは、デーモン自体から分離して扱うのが最良です。これには、サービスの開始を関連ソケットが初めてアクセスされるまで遅らせるなど、いくつかの利点があります。また、これにより、システムはブートプロセスの早い段階で全てのソケットを作成でき、関連サービスを並行してブートすることが可能になります。
- バスベースのアクティベーション: ユニットは、
D-Busによって提供されるバスインターフェイス上でもアクティブ化できます。関連するバスが公開されると、ユニットを起動できます。 - パスベースのアクティベーション:特定のファイルシステムパスにおけるアクティビティまたはその有無に基づいてユニットを開始できます。これは
inotifyを利用しています。 - デバイスベースのアクティベーション: ユニットは、
udevイベントを利用して関連するハードウェアが初めて利用可能になったときに起動することもできます。 - 暗黙の依存関係マッピング: ユニットの依存関係ツリーのほとんどは、
systemd自体によって構築することができます。依存関係や順序情報を追加することはできますが、重い作業のほとんどは自動的に処理されます。 - インスタンスとテンプレート: テンプレートユニットファイルを使用して、同じ一般的なユニットの複数のインスタンスを作成できます。これにより、わずかなバリエーションや、すべてが同じ一般的な機能を提供する兄弟ユニットを作成できます。
- 簡単なセキュリティ強化: ユニットは、簡単な指示を追加することで、かなり良いセキュリティ機能を実装できます。例えば、ファイルシステムの一部に対してアクセスを禁止または読み取り専用に指定したり、カーネルの機能を制限したり、プライベートな
/tmpやネットワークアクセスを割り当てたりできます。 - ドロップインとスニペット:ユニットは、システムのユニットファイルの一部をオーバーライドするスニペットを提供することで簡単に拡張できます。これにより、バニラとカスタマイズされたユニット実装の間で簡単に切り替えることができます。
systemdユニットが他のinitシステムの作業項目に対して持つ多くの利点がありますが、これによりネイティブ構成ディレクティブを使用して得ることができる力のアイデアが得られるはずです。
Systemdユニットファイルはどこにありますか?
systemdがユニットをどのように処理するかを定義するファイルは、さまざまな場所に存在し、それぞれが異なる優先順位と影響を持っています。
システムのユニットファイルのコピーは一般に/lib/systemd/systemディレクトリに保存されます。ソフトウェアがシステムにユニットファイルをインストールする際、デフォルトではここに置かれます。
ここに保存されているユニットファイルは、セッション中にオンデマンドで開始および停止できるようになっています。これは、標準的な実装でsystemdをデプロイする任意のシステムで動作するべき、上流プロジェクトのメンテナによってしばしば書かれる一般的なヴァニラのユニットファイルです。このディレクトリ内のファイルを編集しないでください。必要であれば、ここにあるファイルを上書きする別のユニットファイルの場所を使用してください。
ユニットの動作を変更したい場合、最適な場所は /etc/systemd/system ディレクトリです。このディレクトリにあるユニットファイルは、ファイルシステム上の他の場所のものよりも優先されます。システムのユニットファイルを変更する必要がある場合、このディレクトリに置き換えファイルを配置するのが最も安全で柔軟な方法です。
システムのユニットファイルから特定の指示のみをオーバーライドしたい場合、実際にサブディレクトリ内にユニットファイルのスニペットを提供することができます。これらはシステムのコピーの指示を追加または変更し、変更したいオプションのみを指定できるようにします。
これを正しく行う方法は、ユニットファイル名の後に.dを追加した名前のディレクトリを作成することです。したがって、example.serviceというユニットの場合、example.service.dというサブディレクトリを作成できます。このディレクトリ内では、.confで終わるファイルを使用して、システムのユニットファイルの属性を上書きまたは拡張することができます。
/run/systemd/systemには実行時ユニット定義のための場所もあります。このディレクトリに見つかるユニットファイルは、/etc/systemd/systemと/lib/systemd/systemの間に優先順位があります。この場所のファイルは前者の場所よりも重みが少ないですが、後者のものよりは重みがあります。
systemdプロセス自体は、実行時に動的に作成されたユニットファイルのためにこの場所を使用します。このディレクトリは、セッションの期間中にシステムのユニット動作を変更するために使用できます。このディレクトリで行われたすべての変更は、サーバーが再起動されると失われます。
ユニットの種類
Systemdは、ユニットが説明するリソースのタイプに応じて、ユニットをカテゴリ分けします。ユニットのタイプを判断する最も簡単な方法は、リソース名の末尾に付加されたタイプサフィックスを使用することです。以下のリストは、systemdで利用可能なユニットのタイプを説明しています:
.service: サービスユニットは、サーバー上でのサービスやアプリケーションの管理方法を説明します。これには、サービスの開始または停止の方法、どのような状況で自動的に開始されるべきか、関連ソフトウェアの依存関係および順序情報が含まれます。.socket: ソケットユニットファイルは、systemdがソケットベースのアクティベーションに使用するネットワークまたはIPCソケット、またはFIFOバッファを記述します。これらは常に、定義されたソケットでアクティビティが見られたときに開始される関連する.serviceファイルを持ちます。.device:udevまたはsysfsファイルシステムによってsystemd管理が必要と指定されたデバイスを説明するユニットです。すべてのデバイスに.deviceファイルがあるわけではありません。.deviceユニットが必要とされるシナリオには、デバイスの順序付け、マウント、およびアクセスが含まれます。.mount: このユニットは、systemdによって管理されるシステム上のマウントポイントを定義します。これらはマウントパスにちなんで名付けられ、スラッシュはダッシュに変更されます。/etc/fstab内のエントリには、ユニットが自動的に作成されることがあります。.automount:.automountユニットは、自動的にマウントされるマウントポイントを設定します。これらは、参照されるマウントポイントの名前を持っている必要があり、マウントの詳細を定義するための対応する.mountユニットを持っている必要があります。.swap: このユニットはシステム上のスワップスペースを説明します。これらのユニットの名前は、スペースのデバイスまたはファイルパスを反映する必要があります。.target: ターゲットユニットは、起動時や状態変更時に他のユニットのための同期ポイントを提供するために使用されます。また、システムを新しい状態に持っていくためにも使用できます。他のユニットは、ターゲットの操作に結びつくために、ターゲットへの関係を指定します。.path: このユニットは、パスベースのアクティベーションに使用できるパスを定義します。デフォルトでは、指定された状態にパスが達したときに同じ基本名の.serviceユニットが起動します。これは、inotifyを使用してパスの変更を監視します。.timer:.timerユニットは、cronジョブのように遅延またはスケジュールされたアクティベーションのために、systemdによって管理されるタイマーを定義します。タイマーが到達すると、一致するユニットが開始されます。.snapshot:systemctl snapshotコマンドによって自動的に生成される.snapshotユニットです。変更を加えた後にシステムの現在の状態を再構築することを可能にします。スナップショットはセッションをまたがって持続せず、一時的な状態をロールバックするために使用されます。.slice:.sliceユニットは、Linux 制御グループノードに関連付けられており、スライスに関連付けられたプロセスにリソースを制限または割り当てることができます。この名前は、cgroupツリー内の階層位置を反映しています。ユニットは、そのタイプに応じてデフォルトで特定のスライスに配置されます。.scope: スコープユニットは、systemdがそのバスインターフェースから受け取った情報に基づいて自動的に作成されます。これらは外部から作成されたシステムプロセスのセットを管理するために使用されます。
ご覧の通り、systemdが管理できるさまざまなユニットがあります。多くのユニットタイプは、機能を追加するために協力して機能します。例えば、一部のユニットは他のユニットをトリガーし、アクティベーション機能を提供するために使用されます。
私たちは主に.serviceユニットに焦点を当てる予定です。これはその有用性と、管理者がこれらのユニットを管理する必要がある一貫性に起因しています。
ユニットファイルの構造
ユニットファイルの内部構造はセクションで整理されています。セクションは一対の角括弧「[」と「]」で示され、その間にセクション名が含まれています。各セクションは、次のセクションの開始またはファイルの終わりまで続きます。
ユニットファイルの一般的な特性
セクション名は明確に定義されており、大文字と小文字が区別されます。したがって、セクション [Unit] は [UNIT] のようにつづられた場合、正しく解釈されません。他のアプリケーション(systemd以外)によって解析される非標準のセクションを追加する必要がある場合は、セクション名に X- プレフィックスを追加できます。
これらのセクション内では、ユニットの動作とメタデータは、キーと値の形式を使用したシンプルなディレクティブを介して定義され、代入は等号で示されます。このように:
[Section]
Directive1=value
Directive2=value
. . .
オーバーライドファイル(unit.type.dディレクトリに含まれるようなファイル)が存在する場合、ディレクティブは空の文字列に割り当てることでリセットできます。たとえば、システムのユニットファイルのコピーには、次のような値に設定されたディレクティブが含まれているかもしれません。
Directive1=default_value
default_valueは、値なしでDirective1を参照することで、オーバーライドファイルで削除できます。これにより、以下のようになります:
Directive1=
一般に、systemdは簡単で柔軟な設定を可能にします。例えば、複数のブール式が受け入れられます(肯定的な場合は1、yes、on、およびtrue、否定的な場合は0、no、off、およびfalse)。時刻は賢く解析され、単位なしの値には秒が仮定され、複数のフォーマットを内部的に組み合わせることができます。
[ユニット] セクション指令
ほとんどのユニットファイルに見られる最初のセクションは[Unit]セクションです。これは一般的にユニットのメタデータを定義し、ユニットと他のユニットとの関係を構成するために使用されます。
ファイルを解析する際にsystemdには関係ありませんが、このセクションはユニットの概要を提供するため、通常は最上部に配置されます。[Unit]セクションで見られる一般的なディレクティブには次のようなものがあります:
説明=: このディレクティブはユニットの名前と基本機能を説明するために使用できます。これはさまざまなsystemdツールによって返されるため、短く、特定的で、情報的なものに設定することが良いです。Documentation=: このディレクティブは、ドキュメントのURIリストの場所を提供します。これらは、内部で利用可能なmanページまたはウェブアクセス可能なURLのいずれかです。systemctl statusコマンドはこの情報を公開し、簡単に発見できるようにします。必要条件=: このディレクティブは、このユニットが本質的に依存する任意のユニットを一覧表示します。現在のユニットがアクティブ化されると、ここにリストされているユニットも成功裏にアクティブ化される必要があります。そうでない場合、このユニットは失敗します。これらのユニットは、デフォルトで現在のユニットと並行して開始されます。Wants=: このディレクティブはRequires=に似ていますが、より厳密ではありません。Systemdは、このユニットがアクティブ化されるときに、ここにリストされたユニットを起動しようとします。これらのユニットが見つからない場合や、起動に失敗した場合でも、現在のユニットは機能を続けます。これは、多くの依存関係を設定するための推奨される方法です。再度言うと、これは他のディレクティブによって変更されない限り、並行でのアクティブ化を意味します。BindsTo=: このディレクティブはRequires=に似ていますが、関連するユニットが終了したときに、現在のユニットを停止させる効果もあります。Before=: この指令にリストされているユニットは、現在のユニットが開始されたとマークされるまで、同時に活動されている場合には開始されません。これは依存関係を示すものではなく、これを望む場合は上記の指令のいずれかと一緒に使用する必要があります。After=: この指令に記載されたユニットは、現在のユニットを開始する前に開始されます。これは依存関係を示すものではなく、必要であれば上記の指令を通じて確立される必要があります。Conflict=: これは、現在のユニットと同時に実行できないユニットのリストを示すために使用できます。この関係を持つユニットを開始すると、他のユニットが停止します。Condition...=: 管理者がユニットを開始する前に特定の条件をテストできるConditionで始まるいくつかのディレクティブがあります。これは、適切なシステムのときにのみ実行される一般的なユニットファイルを提供するために使用される可能性があります。条件が満たされない場合、ユニットは優雅にスキップされます。Assert...=:Conditionで始まる指令と似ており、これらの指令はユニットをアクティブにするべきかを判断するために実行環境の異なる側面をチェックします。しかし、Conditionの指令とは異なり、否定的な結果はこの指令による失敗を引き起こします。
これらの指示とその他のいくつかを使用して、ユニットおよびその他のユニットやオペレーティングシステムとの関係に関する一般情報を確立できます。
[インストール] セクションディレクティブ
ユニットファイルの反対側には、最後のセクションとしてしばしば[Install]セクションがあります。このセクションはオプションであり、ユニットが有効または無効のときの動作を定義するために使用されます。ユニットを有効にすることで、それが起動時に自動的に開始されることが示されます。本質的に、これは対象のユニットを起動時に開始されるユニットのいずれかに接続することで達成されます。
これにより、有効にできるユニットのみがこのセクションを持つことになります。内部の指示は、ユニットが有効にされたときに何が起こるべきかを示しています:
WantedBy=:WantedBy=指令は、ユニットを有効にする方法を指定する最も一般的な方法です。この指令により、Wants=指令が[Unit]セクションで行うのと同様に、依存関係の関係を指定できます。違いは、この指令が附属ユニットに含まれているため、リストされた主要なユニットが比較的クリーンに保たれることです。この指令を持つユニットが有効にされると、指定されたユニットの名前のディレクトリが/etc/systemd/system内に作成されます。 最後にwantsが追加されます。この中に、現在のユニットへのシンボリックリンクが作成され、依存関係が形成されます。たとえば、現在のユニットにWantedBy=multi-user.targetがある場合、/etc/systemd/system内にmulti-user.target.wantsというディレクトリが作成され(既に存在しない場合)、その中に現在のユニットへのシンボリックリンクが配置されます。このユニットを無効にすると、リンクが削除され、依存関係も削除されます。RequiredBy=: このディレクティブは、WantedBy=ディレクティブと非常に似ていますが、満たされない場合にはアクティベーションが失敗する必要な依存関係を指定します。有効にすると、このディレクティブを持つユニットは.requiresで終わるディレクトリを作成します。エイリアス =: このディレクティブは、ユニットを別名でも有効にすることを可能にします。他の用途の中で、これにより機能の複数のプロバイダーが利用可能になり、関連ユニットは共通のエイリアス名のプロバイダーを探すことができます。Also=: このディレクティブは、ユニットをセットとして有効または無効にすることを許可します。このユニットがアクティブであるときに常に利用可能であるべきサポートユニットはここにリストできます。インストールタスクのためにグループとして管理されます。DefaultInstance=: 後で説明するテンプレートユニットにおいて、名前が予測できないユニットインスタンスを生成することができる場合、適切な名前が提供されない場合のフォールバック値として使用できます。
ユニット特定セクション指令
前の2つのセクションの間に、特定のユニットタイプに関するセクションがあると思います。ほとんどのユニットタイプは、その特定のタイプにのみ適用される指示を提供します。これらはそのタイプの名前が付けられたセクション内で利用可能です。ここではそれらを簡単に説明します。
device、target、snapshot、およびscopeユニットタイプにはユニット固有のディレクティブがなく、そのためそのタイプに関連するセクションはありません。
[サービス] セクション
[Service]セクションは、サービスにのみ適用される設定を提供するために使用されます。
[Service] セクション内で指定されるべき基本的な事項の一つは、サービスの Type= です。これは、サービスをプロセスとデーモン化の動作によって分類します。これは重要で、systemd にサービスを正しく管理してその状態を把握する方法を伝えます。
このType=ディレクティブは次のいずれかになります:
- シンプル: サービスの主要プロセスは、開始行に指定されています。これは、
Type=およびBusname=ディレクティブが設定されていない場合のデフォルトですが、ExecStart=が設定されている場合です。通信は、必要に応じて、適切なタイプのセカンドユニットを介してユニットの外部で処理する必要があります(このユニットがソケットを使用して通信する必要がある場合は、.socketユニットを介して)。 - フォーク: このサービスタイプは、サービスが子プロセスをフォークし、親プロセスがほぼ直ちに終了する場合に使用されます。これは、親が終了してもプロセスがまだ実行中であることを
systemdに知らせます。 - oneshot: このタイプはプロセスが短命であることを示し、
systemdが他のユニットに進む前にプロセスが終了するのを待つ必要があります。これはデフォルトのType=であり、ExecStart=が設定されていない場合です。一回限りのタスクに使用されます。 - dbus: これは、ユニットがD-Busバス上に名前を取ることを示します。この場合、
systemdは次のユニットの処理を続けます。 - 通知: これは、サービスが起動を完了したときに通知を発行することを示します。
systemdプロセスは、他のユニットに進む前にこれが発生するのを待ちます。 - アイドル: これは、すべてのジョブが配信されるまでサービスが実行されないことを示します。
特定のサービスタイプを使用する際には、追加の指示が必要になる場合があります。例えば:
RemainAfterExit=: このディレクティブは、一般的にoneshotタイプと一緒に使用されます。これは、プロセスが終了した後でもサービスがアクティブと見なされるべきであることを示しています。PIDFile=: サービスの種類が「フォーク」としてマークされている場合、このディレクティブは監視されるべき主な子プロセスのプロセスID番号を含むファイルのパスを設定するために使用されます。BusName=: この指示は、サービスが「dbus」サービスタイプを使用する際に取得しようとするD-Busバス名に設定する必要があります。NotifyAccess=: これは、「notify」サービスタイプが選択されたときに通知をリッスンするために使用されるソケットへのアクセスを指定します。これは「none」、「main」、または「all」のいずれかです。デフォルトは「none」で、すべてのステータスメッセージを無視します。「main」オプションはメインプロセスからのメッセージをリッスンし、「all」オプションはサービスのコントロールグループのすべてのメンバーを処理することになります。
これまで、いくつかの前提情報について議論しましたが、実際にはサービスを管理する方法を定義していません。そのための指示は次の通りです:
ExecStart=: これは、プロセスを開始するために実行されるコマンドの完全なパスと引数を指定します。これは一度だけ指定することができます(「oneshot」サービスを除く)。コマンドのパスの前にダッシュ「-」文字が付いている場合、ゼロ以外の終了ステータスが受け入れられ、ユニットのアクティベーションは失敗としてマークされません。ExecStartPre=: これは、メインプロセスが開始される前に実行されるべき追加のコマンドを提供するために使用できます。これは複数回使用できます。また、コマンドはフルパスを指定する必要があり、コマンドの失敗を許容することを示すために「- 」を前に付けることができます。ExecStartPost=: これはExecStartPre=と全く同じ特性を持ちますが、メインプロセスが開始された 後 に実行されるコマンドを指定します。ExecReload=: このオプションのディレクティブは、サービスの設定を再ロードするために必要なコマンドを示します(利用可能な場合)。ExecStop=: これはサービスを停止するために必要なコマンドを示しています。これが指定されていない場合、サービスが停止されるとプロセスは直ちに終了されます。ExecStopPost=: これは停止コマンドの後に実行するコマンドを指定するために使用できます。RestartSec=: サービスの自動再起動が有効になっている場合、サービスを再起動する前に待機する時間を指定します。Restart=: これは、systemdがサービスを自動的に再起動しようとする状況を示しています。これは、「常に」、「成功時」、「失敗時」、「異常時」、「中止時」、または「ウォッチドッグ時」のような値に設定できます。これにより、サービスが停止した方法に応じて再起動がトリガーされます。TimeoutSec=: これは、systemdがサービスを停止する際に待機する時間を設定します。サービスを失敗としてマークするか、強制的に終了させる前にこの時間を待ちます。また、TimeoutStartSec=およびTimeoutStopSec=を使用して、別々のタイムアウトを設定することもできます。
[ソケット] セクション
ソケットユニットは、より良い並列処理と柔軟性を提供するために、多くのサービスがソケットベースの起動を実装しているため、systemdの構成では非常に一般的です。各ソケットユニットには、ソケットがアクティビティを受け取ったときに起動される対応するサービスユニットが必要です。
サービス自体の外でソケット制御を破ることで、ソケットは早期に初期化され、関連するサービスはしばしば並行して起動されることができます。デフォルトでは、ソケット名は接続を受け取ると同名のサービスを起動しようとします。サービスが初期化されると、ソケットがそれに渡され、バッファに蓄積されたリクエストの処理を開始することができます。
実際のソケットを指定するために、これらの指令は一般的です:
ListenStream=: これは、順次かつ信頼性のある通信をサポートするストリームソケットのアドレスを定義します。TCPを使用するサービスは、このソケットタイプを使用する必要があります。ListenDatagram=: これは、迅速で信頼性のない通信パケットをサポートするデータグラムソケットのアドレスを定義します。UDPを使用するサービスは、このソケットタイプを設定する必要があります。ListenSequentialPacket=: これは、メッセージの境界を保持しながら、最大長のデータグラムを用いた逐次的で信頼性のある通信のためのアドレスを定義しています。これは、Unixソケットで最も一般的に見られます。ListenFIFO: 他のリスニングタイプと共に、ソケットの代わりにFIFOバッファを指定することもできます。
リスニングディレクティブの種類はもっとありますが、上記のものが最も一般的です。
ソケットの他の特性は、追加の指示を通じて制御できます。
Accept=: これは、接続ごとにサービスの追加インスタンスが開始されるかどうかを決定します。false(デフォルト値)に設定されている場合、1つのインスタンスがすべての接続を処理します。SocketUser=: Unixソケットを使用して、ソケットの所有者を指定します。これが設定されていない場合、所有者はrootユーザーになります。SocketGroup=: Unixソケットを使用する場合、ソケットのグループ所有者を指定します。これが設定されていない場合、または上記の設定がない場合、ルートグループになります。もしSocketUser=のみが設定されている場合、systemdは一致するグループを探そうとします。SocketMode=: Unix ソケットまたは FIFO バッファの場合、これにより作成されたエンティティのアクセス権が設定されます。サービス=: サービス名が.socket名と一致しない場合、このディレクティブでサービスを指定できます。
山のセクション
マウントユニットは、systemd内からマウントポイントの管理を可能にします。マウントポイントは、制御するディレクトリにちなんで名付けられ、翻訳アルゴリズムが適用されます。
例えば、最初のスラッシュは削除され、他のすべてのスラッシュはダッシュ「-」に変換され、すべてのダッシュと表示できない文字はCスタイルのエスケープコードに置き換えられます。この翻訳の結果は、マウントユニット名として使用されます。マウントユニットは、その階層内の上位にある他のマウントに暗黙の依存関係を持ちます。
マウントユニットは、ブートプロセス中に通常、/etc/fstabファイルから直接翻訳されます。自動的に作成されるユニット定義と、ユニットファイルで定義したいユニットのために、以下のディレクティブが役立ちます。
What=: マウントする必要があるリソースへの絶対パス。Where=: リソースをマウントする必要があるマウントポイントの絶対パス。この名前はユニットファイル名と同じであるべきですが、従来のファイルシステムの表記を使用する必要があります。タイプ=: マウントのファイルシステムタイプです。オプション=: 適用する必要があるマウントオプション。これはカンマで区切られたリストです。SloppyOptions=: 認識されないマウントオプションがある場合、マウントに失敗するかどうかを決定するブール値です。DirectoryMode=: マウントポイントのために親ディレクトリを作成する必要がある場合、これによりこれらのディレクトリのアクセス許可モードが決まります。TimeoutSec=: システムがマウント操作を失敗としてマークするまでの待機時間を設定します。
[自動マウント]セクション
このユニットは、関連する .mount ユニットがブート時に自動的にマウントされることを許可します。 .mount ユニットと同様に、これらのユニットは翻訳されたマウントポイントのパスに基づいて名前を付ける必要があります。
[Automount] セクションは非常にシンプルで、次の2つのオプションのみが許可されています:
Where=: ファイルシステム上の自動マウントポイントの絶対パスです。これはファイル名と一致しますが、翻訳ではなく従来のパス表記を使用します。DirectoryMode=: 自動マウントポイントまたは親ディレクトリを作成する必要がある場合、これによりそれらのパスコンポーネントの権限設定が決まります。
[スワップ] セクション
スワップユニットは、システム上のスワップ領域を構成するために使用されます。ユニットは、上記で説明したのと同じファイルシステムの翻訳を使用して、スワップファイルまたはスワップデバイスに名前を付ける必要があります。
マウントオプションのように、スワップユニットは自動的に/etc/fstabエントリから作成されるか、専用のユニットファイルを通じて設定することができます。
ユニットファイルの[Swap]セクションには、次の設定用のディレクティブを含めることができます:
What=: スワップスペースの場所への絶対パスであり、これがファイルであるかデバイスであるかにかかわらず。優先度=: これは、設定されているスワップの優先度を示す整数を取ります。オプション=: 通常、/etc/fstabファイルで設定される任意のオプションは、この指令で代わりに設定できます。カンマ区切りのリストが使用されます。TimeoutSec=:systemdがスワップの有効化を待機する時間で、指定された時間内に有効化されない場合は操作を失敗としてマークします。
[パス] セクション
パスユニットは、systmed が変更を監視できるファイルシステムパスを定義します。パス位置で特定のアクティビティが検出されたときにアクティブ化される別のユニットが存在する必要があります。パスアクティビティは、inotify イベントを通じて決定されます。
ユニットファイルの[Path]セクションには、以下のディレクティブを含めることができます。
PathExists=: このディレクティブは、問題のパスが存在するかどうかをチェックするために使用されます。存在する場合、関連付けられたユニットがアクティブになります。PathExistsGlob=: これは上記と同じですが、パスの存在を確認するためにファイルのグロブ式をサポートしています。PathChanged=: これはパスの場所に変更があるかを監視します。監視されたファイルが閉じられたときに変更が検出されると、関連するユニットがアクティブになります。PathModified=: これは上記の指示に似た変更を監視しますが、ファイルの書き込み時やファイルが閉じられたときにもアクティブになります。DirectoryNotEmpty=: このディレクティブは、ディレクトリがもはや空でないときに、関連するユニットをsystemdがアクティブ化できるようにします。Unit=: これは、上記で指定されたパス条件が満たされたときにアクティブにするユニットを指定します。これが省略されると、systemdはこのユニットと同じ基本ユニット名を持つ.serviceファイルを探します。MakeDirectory=: これは、systemdが監視する前に、問題のパスのディレクトリ構造を作成するかどうかを決定します。DirectoryMode=: 上記が有効になっている場合、作成しなければならないパスコンポーネントの権限モードが設定されます。
[タイマー] セクション
タイマー単位は、特定の時間または一定の遅延後にタスクを実行するようにスケジュールするために使用されます。この単位タイプは、cronおよびatデーモンの一部の機能を置き換えるか、補完します。タイマーに達したときにアクティブ化される関連ユニットを提供する必要があります。
ユニットファイルの[Timer]セクションには、以下のいくつかのディレクティブを含めることができます。
OnActiveSec=: このディレクティブは、関連するユニットが.timerユニットのアクティブ状態に対してアクティブ化されることを許可します。OnBootSec=: この指示は、システムが起動した後、関連するユニットがアクティブ化されるべき時間を指定するために使用されます。OnStartupSec=: このディレクティブは上記のタイマーと似ていますが、systemdプロセス自体が開始された時期に関連しています。OnUnitActiveSec=:これは、関連するユニットが最後にアクティブになったときに基づいてタイマーを設定します。OnUnitInactiveSec=: これは、関連するユニットが最後に非アクティブとしてマークされた時間に関するタイマーを設定します。OnCalendar=: これは、イベントに対して相対的ではなく絶対値を指定することにより、関連するユニットをアクティブにすることを可能にします。AccuracySec=: この単位は、タイマーを守るための精度のレベルを設定するために使用されます。デフォルトでは、関連する単位はタイマーが達成されてから1分以内にアクティブになります。この指令の値は、systemdがアクティベーションを行うためのウィンドウの上限を決定します。Unit=: このディレクティブは、タイマーが経過したときにアクティブにすべきユニットを指定するために使用されます。設定されていない場合、systemdはこのユニットと名前が一致する.serviceユニットを探します。Persistent=: これが設定されている場合、systemdはタイマーが非アクティブであった期間中にトリガーされていたであろうときに、タイマーがアクティブになったときに関連付けられたユニットをトリガーします。WakeSystem=: このディレクティブを設定すると、システムがサスペンド状態にあるときに、タイマーが到達した際にシステムをウェイクアップできます。
[スライス] セクション
ユニットファイルの[Slice]セクションには、実際には.sliceユニット特有の設定はありません。代わりに、上記のいくつかのユニットに利用可能なリソース管理ディレクティブが含まれていることがあります。
[Slice]セクションで一般的に使用される指示のいくつかは、他のユニットでも使用されることがあります。それらはsystemd.resource-controlマニュアルページに見つけることができます。これらは次のユニット固有のセクションで有効です:
[Slice][Scope][Service][Socket][Mount][Swap]テンプレートユニットファイルからインスタンスユニットを作成する
このガイドの前の部分で、テンプレートユニットファイルを使用して複数のユニットのインスタンスを作成するというアイデアについて言及しました。このセクションでは、この概念をより詳細に説明します。
テンプレートユニットファイルは、ほとんどの点で通常のユニットファイルと異なりません。しかし、これらはファイルの特定の部分が実行時に利用可能な動的情報を活用することを可能にすることによって、ユニットの構成に柔軟性を提供します。
テンプレートとインスタンスユニット名
テンプレートユニットファイルは、基本ユニット名の後に@シンボルがあり、ユニットタイプサフィックスの前にあるため識別できます。テンプレートユニットファイル名はこのようになります:
example@.service
テンプレートからインスタンスが作成されると、インスタンス識別子が@記号とユニットタイプの開始を示すピリオドの間に配置されます。例えば、上記のテンプレートユニットファイルは、次のようなインスタンスユニットを作成するために使用できます:
example@instance1.service
インスタンスファイルは通常、テンプレートファイルへのシンボリックリンクとして作成され、そのリンク名にはインスタンス識別子が含まれます。このようにして、ユニークな識別子を持つ複数のリンクが単一のテンプレートファイルを指し示すことができます。インスタンスユニットを管理する際、systemd は、コマンドラインで指定した正確なインスタンス名のファイルを使用するために探します。一致するファイルが見つからない場合は、関連するテンプレートファイルを探します。
テンプレート指定子
テンプレートユニットファイルの力は、主に実行環境に応じてユニット定義内で適切な情報を動的に置き換える能力によって示されます。これは、テンプレートファイル内の指令を通常通り設定しながら、特定の値や値の一部を変数指定子で置き換えることで行われます。
以下は、インスタンスユニットが関連情報で解釈される際に置き換えられる一般的なスペシファイアのいくつかです。
%n: テンプレートファイルにこの部分が現れると、完全な結果の単位名が挿入されます。%N: これは上記と同じですが、ファイルパスパターンに存在するエスケープなどは逆になります。%p: これは単位名の接頭辞を参照します。これは、単位名の中で@記号の前に来る部分です。%P: これは上記と同じですが、エスケープが逆転しています。%i:これはインスタンス名を参照しており、インスタンスユニット内の@の後に続く識別子です。これは、動的であることが保証されるため、最も一般的に使用される指定子の1つです。この識別子の使用は、構成に重要な識別子の使用を促進します。たとえば、サービスが実行されるポートをインスタンス識別子として使用でき、テンプレートはこの指定子を使用してポート仕様を設定できます。%I: この指定子は上記と同じですが、エスケープが逆転しています。%f: これはアンエスケープされたインスタンス名または接頭辞名に置き換えられ、/が前に付けられます。%c: これは、標準の親階層/sys/fs/cgroup/systemd/が削除されたユニットの対照群を示します。%u: ユニットを実行するために設定されたユーザーの名前。%U: 上記と同様ですが、名前の代わりに数値のUIDです。%H: ユニットを実行しているシステムのホスト名です。%%: これはリテラルのパーセント記号を挿入するために使用されます。
上記の識別子をテンプレートファイルで使用することにより、systemd はテンプレートを解釈してインスタンスユニットを作成する際に正しい値を埋め込みます。
結論
systemdを使用する際、ユニットおよびユニットファイルを理解することで管理が容易になる場合があります。他の多くのinitシステムとは異なり、サービスやシステムを起動するために使用されるinitファイルを解釈するためにスクリプト言語を知っている必要はありません。ユニットファイルは、ユニットがアクティベーションされたときの目的や影響を一目で確認できる、かなり直截的な宣言的構文を使用しています。
アクティベーションロジックなどの機能を別のユニットに分割することは、内部のsystemdプロセスが並列初期化を最適化できるだけでなく、設定を比較的シンプルに保ち、関連する接続を壊して再構築することなくいくつかのユニットを変更し再起動することを可能にします。これらの能力を活用することで、管理中により多くの柔軟性と権限を得ることができます。