ウェブサイト検索

Linuxでsystemdサービスユニットを作成する方法


systemd は多くの論争の対象となってきましたが、一部のディストリビューションはそれを取り除くためだけにフォークされました (デフォルトで systemd を sysvinit に置き換える Debian のフォークである Devuan を参照)。 Linux の世界における事実上の標準の init システム。

このチュートリアルでは、systemd サービスがどのように構成されているかを確認し、サービスを作成する方法を学びます。 1 つ

このチュートリアルでは次のことを学びます:

  • サービスユニットとは..

  • サービスユニットのセクションとは何ですか。

  • 各セクションで使用できる最も一般的なオプションは何ですか。

  • 定義できるサービスにはどのような種類がありますか。

systemd init システム

Rhel、CentOS、Fedora、Ubuntu、Debian、Archlinux などの主要なディストリビューションはすべて、init システムとして systemd を採用しています。 Systemd は実際のところ、単なる init システムではありません。これが、一部の人々がその設計に強く反対する理由の 1 つであり、「1 つのことを実行すれば、それをうまく行う」という確立された UNIX のモットーに反します。他の init システムが単純なシェル スクリプトを使用してサービスを管理するのに対し、systemd は独自の .service ファイル (.service サフィックスが付いたユニット) を使用します。このチュートリアルでは、それらがどのように構造化されているか、および作成方法を説明します。 1つをインストールします。

サービスユニットの構造

サービスユニットとは何ですか? .service サフィックスが付いたファイルには、systemd によって管理されるプロセスに関する情報が含まれています。これは 3 つの主要なセクションで構成されています。

  • [ユニット]: このセクションには、サービスの説明など、ユニットの種類に特に関係しない情報が含まれます。

  • [サービス]: ユニットの特定のタイプに関する情報が含まれます。この場合はサービスです。

  • [インストール]: このセクションにはユニットのインストールに関する情報が含まれています

それぞれを詳しく分析してみましょう。

[単位]セクション

.service ファイルの [Unit] セクションには、ユニット自体の説明と、その動作とその依存関係に関する情報が含まれています (サービスが正しく動作するためには、次のものに依存できます)もう一つ)。ここでは、このセクションで使用できる最も関連性の高いオプションのいくつかについて説明します。

「説明」オプション

まず、Description オプションがあります。このオプションを使用すると、ユニットの説明を提供できます。この説明は、たとえば、systemd のステータスの概要を返す systemctl コマンドを呼び出すときに表示されます。ここでは、例として、Fedora システム上で httpd サービスの記述がどのように定義されているかを示します。

[Unit]
Description=The Apache HTTP Server

「後」オプション

After オプションを使用すると、スペース区切りのリストの形式で提供するユニットの後にユニットを開始する必要があると指定できます。たとえば、Apache Web サービスが定義されているサービス ファイルを再度観察すると、次のことがわかります。

After=network.target remote-fs.target nss-lookup.target httpd-init.service

上記の行は、networkremove-fsnss-lookup< の後にのみサービス ユニット httpd.service を開始するように systemd に指示します。 ターゲットと httpd-init サービス

「Requires」によるハード依存関係の指定

上で簡単に述べたように、ユニット (この場合はサービス) は、正しく動作するために他のユニット (必ずしも「サービス」ユニットではない) に依存することができます。そのような依存関係は、Requires オプションを使用して宣言できます。

サービスが依存するユニットのいずれかが開始に失敗すると、サービスのアクティブ化が停止します。これが、これらが ハード依存関係 と呼ばれる理由です。 avahi-daemon のサービス ファイルから抽出されたこの行では、avahi-daemon.socket ユニットからの依存関係としてどのように宣言されているかがわかります。

Requires=avahi-daemon.socket

「ウォンツ」による「ソフト」依存関係の宣言

Requires オプションを使用して、サービスのいわゆる「ハード」依存関係を宣言する方法を説明しました。 Wants オプションを使用して、「ソフト」依存関係をリストすることもできます。

違いはなんですか?上で述べたように、「ハード」依存関係が失敗すると、サービス自体も失敗します。ただし、「ソフト」依存関係が失敗しても、依存するユニットの動作には影響しません。提供された例では、 docker.service ユニットが docker-storage-setup.service ユニットに対してどのようにソフトな依存関係を持っているかがわかります。

[Unit]
Wants=docker-storage-setup.service

[サービス]セクション

service ユニットの [Service] セクションでは、サービスの開始時に実行するコマンドやサービス自体の種類を指定できます。そのうちのいくつかを見てみましょう。

サービスの開始、停止、リロード

サービスは開始、停止、再起動、またはリロードできます。これらの各アクションを実行するときに実行されるコマンドは、[Service] セクションの関連オプションを使用して指定できます。

サービスの開始時に実行されるコマンドは、ExecStart オプションを使用して宣言されます。オプションに渡される引数は、スクリプトへのパスにすることもできます。オプションで、 ExecStartPre オプションと ExecStartPost オプションをそれぞれ使用して、サービスの開始前と開始後に実行されるコマンドを宣言できます。 NetworkManager サービスを開始するために使用されるコマンドは次のとおりです。

[Service]
ExecStart=/usr/sbin/NetworkManager --no-daemon

同様の方法で、ExecStop オプションと ExecReload オプションを使用して、サービスがリロードまたは停止されたときに実行されるコマンドを指定できます。 ExecStartPost の場合と同様に、プロセスの停止後に起動する 1 つまたは複数のコマンドを ExecStopPost オプションで指定できます。

サービスの種類

Systemd は、予期される動作に応じて、いくつかの異なるタイプのサービスを定義し、区別します。サービスのタイプは、Type オプションを使用して次のいずれかの値を指定して定義できます。

  • 単純

  • フォーク

  • ワンショット

  • dバス

  • 通知する

Type オプションと Busname オプションが定義されていないが、コマンドが ExecStart オプションを介して提供されている場合、サービスのデフォルトのタイプは シンプル。このタイプのサービスが設定されている場合、ExecStart で宣言されたコマンドがメイン プロセス/サービスとみなされます。

forking タイプの動作は異なります。ExecStart で提供されるコマンドは、メイン プロセス/サービスとなる子プロセスをフォークして起動することが期待されます。起動プロセスが終了すると、親プロセスは終了すると予想されます。

Type オプションと ExecStart オプションが定義されていない場合は、oneshot タイプがデフォルトとして使用されます。これは simple とほとんど同じように動作します。違いは、他のユニットが起動される前にプロセスがジョブを完了することが期待されることです。ただし、RemainAfterExit オプションが「yes」に設定されている場合 (デフォルトは「no」)、コマンドが終了した後でもユニットは「アクティブ」とみなされます。

次のタイプのサービスは dbus です。このタイプのサービスが使用される場合、デーモンは BusName オプションで指定されているように Dbus から名前を取得することが期待されます。この場合、これは必須になります。残りの部分については、simple タイプと同様に機能します。ただし、後続のユニットは、DBus 名が取得された後にのみ起動されます。

もう 1 つのプロセスは simple と同様に機能し、それは notify です。違いは、デーモンが sd_notify 関数を介して通知を送信することが期待されることです。この通知が送信されると、その後のユニットが起動されます。

プロセスのタイムアウトを設定する

特定のオプションを使用すると、サービスのタイムアウトを定義できます。 RestartSec から始めましょう: このオプションを使用すると、サービスを再起動する前に systemd が待機する時間 (デフォルトでは秒単位) を設定できます。 「5 分 20 秒」のように、このオプションの値としてタイムスパンを使用することもできます。デフォルトは 100ms です。

TimeoutStartSec オプションと TimeoutStopSec オプションを使用して、それぞれサービスの起動と停止のタイムアウトを秒単位で指定できます。最初のケースでは、指定されたタイムアウトを過ぎてもデーモンの起動プロセスが完了しない場合、失敗したとみなされます。

2 番目のケースでは、サービスを停止する必要があるが、指定されたタイムアウト後に終了しない場合、最初に SIGTERM が実行され、次に同じ時間が経過した後に SIGKILL が実行されます。信号が送信されます。どちらのオプションもタイムスパンを値として受け入れ、ショートカット TimeoutSec を使用して一度に設定できます。 infinity が値として指定された場合、タイムアウトは無効になります。

最後に、RuntimeMaxSec を使用して、サービスの実行時間の制限を設定できます。サービスがこのタイムアウトを超えると、サービスは終了され、失敗したとみなされます。

[インストール]セクション

[install] セクションでは、サービスのインストールに関連するオプションを使用できます。たとえば、Alias オプションを使用すると、systemctl コマンド (enable を除く) を使用するときにサービスに使用するエイリアスのスペース区切りのリストを指定できます。

[Unit] セクションの Requires オプションと Wants オプションを使用して依存関係を確立する場合と同様に、[install] セクションでは、RequiredByWantedBy を使用できます。どちらの場合も、構成しているユニットに依存するユニットのリストを宣言します。前者のオプションではユニットにハード依存し、後者のオプションでは弱い依存とみなされます。例えば:

[Install]
WantedBy=multi-user.target

上の行で、multi-user ターゲットがユニットに対してソフトな依存関係があることを宣言しました。 systemd 用語では、.target 接尾辞で終わるユニットは、他の init システムでは Sysvinit として runtimes と呼ばれるものに関連付けることができます。したがって、私たちの場合、マルチユーザー目標に達した場合、その目標には私たちのサービスが含まれるはずです。

サービスユニットの作成とインストール

systemd サービスユニットがインストールされるファイルシステムには基本的に、/usr/lib/systemd/system/etc/systemd/system の 2 つの場所があります。前者のパスは、インストールされたパッケージによって提供されるサービスに使用されますが、後者のパスは、システム管理者がデフォルトのサービスをオーバーライドできる独自のサービスに使用できます。

カスタム サービスの例を作成してみましょう。特定のイーサネット インターフェイス (この場合は ens5f5) の wake-on-lan 機能を開始時に無効にし、停止時に再度有効にするサービスを作成するとします。 ethtool コマンドを使用して、主要なタスクを実行できます。サービス ファイルは次のようになります。

[Unit]
Description=Force ens5f5 ethernet interface to 100Mbps
Requires=Network.target
After=Network.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/sbin/ethtool -s ens5f5 wol d
ExecStop=/usr/sbin/ethtool -s ens5f5 wol g

[Install]
WantedBy=multi-user.target

簡単なユニットの説明を設定し、サービスが network.target ユニットに依存し、ユニットに到達した後に起動する必要があることを宣言しました。 [Service] セクションでは、サービスのタイプを oneshot として設定し、 を使用してコマンドの実行後にサービスがアクティブであるとみなすように systemd に指示しました。 >RemainAfterExit オプション。また、サービスの開始時と停止時に実行されるコマンドも定義しました。最後に、[Install] セクションで、サービスを multi-user ターゲットに含める必要があることを基本的に宣言しました。

サービスをインストールするには、ファイルを /etc/systemd/system ディレクトリに wol.service としてコピーし、開始します。

$ sudo cp wol.service /etc/systemd/system && sudo systemctl start wol.service

次のコマンドを使用して、サービスがアクティブであることを確認できます。

$ systemctl is-active wol.service
active

コマンドの出力は、予想どおり、active です。ここで、「wake on lan」が d に設定され、無効になっていることを確認するには、次のコマンドを実行します。

$ sudo ethtool ens5f5|grep Wake-on
Supports Wake-on: pg
Wake-on: d

ここで、サービスを停止すると逆の結果が生成され、wol が再度有効になります。

$ sudo systemctl stop wol.service && sudo ethtool ens5f5|grep Wake-on
Supports Wake-on: pg
Wake-on: g

結論

このチュートリアルでは、systemd サービス ファイルがどのように構成されるか、そのセクションとは何か、そして各セクションで使用できるいくつかのオプションについて説明しました。サービスの説明を設定し、その依存関係を定義し、サービスの開始、停止、またはリロード時に実行する必要があるコマンドを宣言する方法を学びました。

systemd は好むと好まざるにかかわらず、Linux の世界では標準の init システムになっているため、その動作方法に慣れることが重要です。 systemd サービスの公式ドキュメントは、freedesktop Web サイトにあります。 systemd を使用したサービスの管理に関する記事もお読みください。

関連記事: