【Linux】systemd:Unit定義ファイル(サービス)の自作とsystemctlによる登録

時計 2021.11.12 / 時計

【Linux】systemd:Unit定義ファイル(サービス)の自作とsystemctlによる登録

本記事ではLinux系OSにおける、Unit定義ファイル(サービス)自作してsystemctlで登録する方法について解説していきます。

systemdの仕組みを使うことで、自作サービスを簡単に定義することができます。
Unit定義ファイルを作成して所定の場所に保存するだけで、簡単にサービスとして登録できます。

本記事を通して以下の知識を学べます。

学べる知識
  • Unit定義ファイルについて
  • Unit(サービス)の自作方法
  • Unit定義ファイルの構成
  • systemctlによる自動起動登録

Unit設定ファイル(定義ファイル)

systemdはunit(ユニット)という単位でサービス(処理)を管理しており、各unitで設定ファイル(定義ファイル)が存在します。

ユニット(サービス)の設定ファイルは自分で作成することができるため、自分の環境にあったサービスを作成することができます。

Unit設定ファイル:保存場所

Unit設定ファイルの保存場所は以下2つのディレクトリ配下にあります。

  1. /usr/lib/systemd/system
  2. /etc/systemd/system

1番は初期の保存先(パッケージのサービスファイルを配置する場所)であり、ここのファイルを編集することはありません。
2番には初期設定を上書きする場合や自作のUnit設定ファイルを作成した場合に、それらファイルを置きます。

1番と2番のディレクトリに同じ名前のUnit設定ファイルがあった場合、2番のファイルが優先されます。

そのため初期設定を上書きしたい場合は、2番のディレクトリにファイルを置きます。

基本的には1番にある設定ファイルを2番のディレクトリにコピーして、コピーしたファイルを修正して利用します。

Unit設定ファイル:ファイルの構成と作成

自作のUnit設定ファイルは/etc/systemd/systemディレクトリ内に作成します。

設定ファイルは3つのセクションから成ります。

セクション名 説明
[Unit] Unitの依存関係など、Unitに依存しない設定
[Service] サービスに関係する設定
[Install] system enable/disableコマンド実行時の設定

Unitの設定ファイルは、上記3つのセクション内に各設定項目を記述して作成していきます。

参考として/usr/lib/systemd/system/nginx.serviceの内容を以下に記します。

[Unit]
Description=A high performance web server and a reverse proxy server
Documentation=man:nginx(8)
After=network.target

[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t -q -g 'daemon on; master_process on;'
ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;'
ExecReload=/usr/sbin/nginx -g 'daemon on; master_process on;' -s reload
ExecStop=-/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid
TimeoutStopSec=5
KillMode=mixed

[Install]
WantedBy=multi-user.target

[Unit]

[Unit]セクションでの設定項目は以下の通りです。

  • Description
  • Documentation
  • Requires
  • Wants
  • After
  • Before
  • Conflicts

Description

Descriptionにはユニット(サービス)の説明を記述します。

systemctl statusコマンドを実行した際に、Descriptionに記述した内容が表示されます。

Documentation

DocumentationにはドキュメントのURIを記述します。

Requires

Requiresにはユニットが必要とする(依存する)ユニットを指定します。

指定したユニットが起動失敗すると、このユニットは起動しません。

Wants

Wantsにはユニットが必要とする(依存する)ユニットを指定します。

Requiresとは異なり、指定したユニットが起動失敗しても、このユニットは起動を継続します。

After

Afterにはこのユニットよりも先に起動している必要があるユニットを指定します。

Afterは依存関係ではなく起動する順番を指定するために利用します。

Before

Beforeにはこのユニットよりも後に起動する必要があるユニットを指定します。

Afterと同様に、依存関係ではなく起動する順番を指定します。

Conflicts

Conflictsにはこのユニットと一緒に起動しないユニットを指定します。

[Service]

[Service]セクションでの設定項目は以下の通りです。

  • ExecStart
  • ExecReload
  • ExecStop
  • ExecStartPre/ExecStartPost
  • ExecStopPost
  • EnvironmentFile
  • Type
  • PIDFile
  • BusName
  • Restart
  • PrivateTmp

ExecStart

ExecStartにはサービス起動時に実行するコマンドを指定します。

必ずフルパスで、引数なども省くことなく記述します。

ExecReload

ExecReloadにはサービスがリロードされた時に実行するコマンドを指定します。

ExecStop

ExecStopにはサービスを停止するコマンドを指定します。

ExecStartPre/ExecStartPost

ExecStartPre/ExecStartPostにはサービスの起動前後の追加コマンドを指定します。

ExecStopPost

ExecStopPostにはサービスの停止後に実行するコマンドを指定します。

ここで指定したコマンドは、サービスが異常終了した場合でも実行されます。

EnvironmentFile

EnvironmentFileには環境変数を読み込むファイルを指定します。

Type

Typeにはサービスの「起動完了」の判定タイミングを指定します。

サービスはExecStartの指定コマンドで起動します。このサービスがどの時点で「起動完了」と判断するかを、以下6つの中から選択します。

指定値 説明
simple コマンドを実行した時点
forking 実行したコマンドが終了した時点
oneshot コマンドを実行した時点(自身のサービスを終了)
notify sd_notify()関数で起動完了メッセージを受け取った時点
dbus D-Bus上に接続名が現れた時点
idle 他ジョブが終了するまで待機

Typeの指定がなければ、simpleが自動的に指定されます。

BusName

BusNameにはD-Bus型のサービスbus接続名を指定します。

Restart

Restartにはサービス(プロセス)が停止したときの動作を指定します。

指定できる動作は以下の4つです。

  • always:常に再起動を試みる
  • no:再起動を行わない
  • on-success:終了コードが0で停止した場合、再起動を試みる
  • on-failure:終了コードが0以外で停止した場合、再起動を試みる

PrivateTmp

PrivateTmpはサービス専用のディレクトリ(/tmpと/var/tmp)を作成するかを指定します。

指定する値はtrueまたはfalseです。

[Install]

[Install]セクションでの設定項目は以下の通りです。

  • WantedBy
  • RequiredBy
  • Also
  • Alias

WantedBy

WantedByは「systemctl enable」コマンドを実行して自動起動を有効化ときに、このユニット(サービス)の「.wants」ディレクトリにシンボリックリンクを作成するか指定します。

IT用語の確認

シンボリックリンクとは対象ファイルまでのパスを含んだ小さな特殊ファイルです

基本的には「multi-user.target」(ランレベル3)または「graphical.target」(ランレベル5)、「default.target」などを指定します。

RequiredBy

RequiredByは「systemctl enable」コマンドを実行して自動起動を有効化ときに、このユニット(サービス)の「.required」ディレクトリにシンボリックリンクを作成するか指定します。

基本的には「multi-user.target」(ランレベル3)または「graphical.target」(ランレベル5)、「default.target」などを指定します。

Also

Alsoは「systemctl enable/disable」コマンドを実行した際に、enable/disableするか指定します。

Alias

Aliasは「systemctl enable」コマンドを実行した際に、指定された名前のシンボリックリンクを作成します。

自作Unit設定ファイルの作成手順

Unit設定ファイルを作成する際の作成手順の一例を示します。
ここでは以下の流れでUnit設定ファイルを作成し、自動起動に登録していきます。

  1. 実行ファイルの作成(bashやPythonなど)
  2. Unit設定ファイルを作成(/etc/systemd/systemディレクトリに保存し、ファイル名は〇〇.service)
  3. 設定ファイルに設定値を書き込む
  4. サービスとして認識されたか確認
  5. 自動起動に登録

1.実行ファイルの作成

ファイル名「office54.sh」という簡単なプログラムを作成します。
まずはvimコマンドでファイルを作成します。

$ sudo vim /usr/local/bin/office54.sh

ファイルの中身は以下のようにしました。

#!/bin/sh
while true
do
   date >> /tmp/office54.log
   sleep 1
done

作成した実行ファイルに「chmod」コマンドで権限を付与します。

$ sudo chmod +x /usr/local/bin/office54.sh

2.Unit設定ファイルを作成

ユニット(サービス)の設定ファイルを/etc/systemd/systemディレクトリに作成します。

$ sudo vim /etc/systemd/system/office54.service

3.設定ファイルに設定値を書き込む

設定ファイルの中身は次のようにしました。

[Unit]
Description = office54 daemon

[Service]
ExecStart = /usr/local/bin/office54.sh
Restart = always
Type = simple

[Install]
WantedBy = multi-user.target

4.Unitがサービスとして認識されたかの確認

作成したUnit設定ファイルがサービスとして認識したか確認します。

確認するためにsystemctlコマンドを次のように使用します。

$ sudo systemctl list-unit-files –type=service | grep office54

表示されればサービスとして認識されています。

5.自動起動の登録

作成したサービスを「systemctl enable」コマンドを実行して自動起動に追加します。

$ sudo systemctl enable office54

実際に起動してみて、そのサービスの状態も確認してみます。

$ sudo systemctl start office54
$ sudo systemctl status office54
● office54.service - office54 daemon
     Loaded: loaded (/etc/systemd/system/office54.service; disabled; vendor pre>
     Active: active (running) since Fri 2021-11-12 10:28:27 JST; 6s ago

念のためログが取れているか以下のコマンドで確認します。

$ tail -f /tmp/office54.log
Fri Nov 12 10:29:23 JST 2021
Fri Nov 12 10:29:24 JST 2021
Fri Nov 12 10:29:25 JST 2021
Fri Nov 12 10:29:26 JST 2021

この流れで作成したユニット(サービス)を自動起動に登録することができます。

まとめ

本記事「【Linux】systemd:Unit定義ファイル(サービス)の自作とsystemctlによる登録」はいかがでしたか。

Unit定義ファイルを作成してサービスを自作できると、Linuxサーバーでできることの幅が広がります。

ぜひ本記事で学んだことを実際にサーバーで利用してください。