「設定 - Systemdサービスユニット」の版間の差分

📢 Webサイト閉鎖と移転のお知らせ
このWebサイトは2026年9月に閉鎖いたします。
新しい記事は移転先で追加しております。(旧サイトでは記事を追加しておりません)

ページの作成:「== 概要 == サービスとは、PCの起動時に自動的に実行され、バックグラウンドで仕事をするために待機するソフトウェアのこと…」
 
 
(同じ利用者による、間の15版が非表示)
30行目: 30行目:
<br>
<br>
Systemdではセクションと呼ばれ、その中に一連のキーと値のペア(Systemdではディレクティブと呼ばれる)が格納されている。<br>
Systemdではセクションと呼ばれ、その中に一連のキーと値のペア(Systemdではディレクティブと呼ばれる)が格納されている。<br>
<br><br>
== コマンドライン ==
コマンドラインやターミナルでSystemdを管理するツールはsystemctlと呼ばれる。<br>
<br>
多くのコマンドはシステムに深く介入するため、root権限が必要である。<br>
そのため、必要な操作を行うには、このコマンドをスーパユーザ権限で実行する必要がある。<br>
<br><br>
== ログ ==
Systemdは、ログ情報を中央のジャーナルに書き込む。<br>
これは、<code>journalctl</code>コマンドにより読み出すことができ、検索やフィルタのオプションも含まれている。<br>
<br><br>
== システム全体の単位 ==
usr/lib/systemd/systemディレクトリには、サービスによってシステム全体にプレインストールされているユニットの全てのファイルがある。<br>
<br>
/etc/systemd/systemディレクトリには、ユーザが作成または編集したシステム全体のユニットの全てのファイルがある。<br>
/etc/systemd/systemディレクトリと/usr/lib/systemd/systemdディレクトリで同名のユニットファイルがある場合は、<br>
/etc/systemd/systemディレクトリのファイルが優先される。<br>
<br><br>
== ユニットの種類 ==
ユニットには様々な種類があり、ファイルの拡張子に応じてsystemdの扱いが異なる。<br>
<br>
<center>
{| class="wikitable" style="background-color:#fefefe;"
|+ Systemdユニットファイルの種類
|-
! style="background-color:#66CCFF;" | 種類(拡張子)
! style="background-color:#66CCFF;" | 説明
|-
| .device || デバイスファイルを作成する。
|-
| .mount || ファイルシステムのマウントとアンマウントをする。
|-
| .path || ファイルやディレクトリの変更に応じたサービスユニットを実行する。
|-
| .network || ネットワークの設定を行う。
|-
| .service || サービスを設定する。
|-
| .socket || プロセス間の接続を確立する。
|-
| .target || ユニットのグループを定義する。
|-
| .timer || Cronジョブのような定期的なタスクを実行する。
|}
</center>
<br>
ここでは、.service拡張子のユニットについて記載する。<br>
<br><br>
== ユニットファイルの構造 ==
ユニットファイルは、3つのセクションで構成される。<br>
* [Unit]セクション
*: 依存関係や順次関係等、依存しない設定を記述する。
* [Install]セクション
*: <code>systemctl enable / disable</code>コマンドに関連する設定を記述する。
* [Service]セクション
*: 固有の設定項目を記述する。
<br>
オプションに複数の項目を記述する時は、スペース区切り、または、同じオプションを複数回に分けて記述する。<br>
# スペース区切り
After=NetworkManager.service systemd-resolved.service
# 複数回に分ける
After=NetworkManager.service
After=systemd-resolved.service
<br>
* [Unit]セクション
*: ユニットの種類によらない一般的なオプションの設定
** Description
**: このユニットの説明を記述する。
**: <code>sudo systemctl status</code>を実行する時に表示される。
** Documentation
**: このユニットについてのドキュメントのURIを記述する。
** After
**: このユニットの前に起動するユニットを記述する。
** Before
**: このユニットの後に起動するユニットを記述する。
** Requires
**: このユニットが依存するユニットを記述する。
**: 前のユニットの起動が失敗した場合は起動しない。
** Wants
**: このユニットが依存するユニットを記述する。
**: 前のユニットの起動が失敗した場合でも起動する。
** Conflicts
**: 同時に有効化してはいけないユニットを指定する。
*: <br>
* [Service]セクション
*: サービスに関する設定を記述する。
** Type
**: プロセスの起動方法を記述する。
**: 各方法は以下の6通りある。
**: <u>"起動が完了する"</u>とは、次の他ユニットが実行可能であることを意味する。
*** simple
***: デフォルト。コマンドを実行した時点で起動完了と判定する。
***: 指定コマンドがフォアグラウンドで実行を継続する場合に使用する。
*** forking
***: 子プロセスをバックグラウンドで起動して、親プロセスが終了した時点(最初のコマンドが終了した時点)で起動完了と判定する。
***: 最初のコマンドが終了する場合に使用する。
*** oneshot
***: simpleと似ているが、次のユニットを実行する前に自身のプロセスを終了する。(コマンドが終了したら起動完了と判定して、サービスも終了したものと認識する)
***: <code>RemainAfterExit=yes</code>を指定する場合は、コマンド終了後もサービスは起動したままと認識する。
***: 1度だけコマンドを実行するタイプの場合に使用する。
*** dbus
***: D-Bus(プロセス間通信用メッセージバス)を使用するプロセスであり、<code>BusName</code>で指定した接続名がD-Busに登録される時点で起動完了と判定する。
*** notify
***: simpleと似ているが、systemdのライブラリ関数である<code>sd_notify</code>関数を使用して、起動完了のメッセージを受信した時に起動が完了する。
***: コマンドのプログラムにおいて、<code>sd_notify</code>関数を使用して起動完了を通知するように設計されている必要がある。
*** idle
***: simpleと似ているが、他のジョブが終了するまで待機する。(シェルへの出力が混ざらないようにするため)
** ExecStart
**: 起動時に実行するコマンドを記述する。
** ExecStop
**: 停止時に実行するコマンドを記述する。
** ExecReload
**: リロード時に実行するコマンドを記述する。
** Restart
**: プロセスが異常終了した時、プロセスを再起動する条件を記述する。
**: 未指定の場合、<u>10秒の間に5回以上再起動すると、次の10秒間は再起動を試みない。</u>
**: <br>
**: <code>StartLimitInterval</code>秒の間に<code>StartLimitBurst</code>回以上再起動すると、次の<code>StartLimitInterval</code>秒の間は再起動を試みない。
**: <br>
**: 各条件は以下の4つがある。
*** always
***: 常に自動的に再起動する。
*** no
***: 再起動しない。
*** on-success
***: 終了コードが0で再起動する。
*** on-failure
***: 終了コードが0以外で再起動する。
*** on-abort
***: キャッチできないシグナルで終了した時に再起動する。
*** on-watchdog
***: 監視時間切れで再起動する。
*** on-abnormal
***: SIGHUP、SIGINT、SIGTERM、SIGPIPE以外のシグナルで終了した時に再起動する。
** RestartSec
**: 再起動するまでの待ち時間(秒)を記述する。
** ExecStartPreおよびExecStartPost
**: サービス起動前(ExecStartPre)およびサービス起動後(ExecStartPost)の追加コマンドを指定する。
**: これは、サービスの起動判定には関連させたくないコマンドを指定する。
** ExecStopPost
**: サービス停止後に実行するコマンドを指定する。
**: これは、サービスが異常終了した場合にも実行される。
** KillMode
**: ExecStopで停止せずに残ったプロセスの処理方法を指定する。
*** none
***: 残プロセスは放置する。
*** process
***: メインプロセスが残っている場合、SIGTERM / SIGKILLで停止する。
***: その他の残プロセスは放置する。
*** control-group
***: グループ内の全ての残プロセスをSIGTERM / SIGKILLで停止する。
*** mixed
***: メインプロセスをSIGTERM / SIGKILLで停止して、続けてグループ内の全ての残プロセスをSIGKILLで停止する。
** PIDFile
**: fork型サービスのメインプロセスのPIDファイルを指定する。
** BusName
**: D-Bus型サービスのbus接続名を指定する。
** User
**: プロセスを起動するユーザを指定する。
** Group
**: プロセスを起動するグループを指定する。
** PrivateTmp
**: このサービス専用の/tmpと/var/tmpを用意する。
** ReadOnlyDirectories
**: 指定ディレクトリ以下をReadOnlyモードにする。
** InaccessibleDirectories
**: 指定ディレクトリ以下をアクセス不可にする。
** RootDirectory
**: 指定ディレクトリにchrootする。
* [Install]セクション
*: インストール時の設定を記述する。
** Alias
**: <code>sudo systemctl enable</code>コマンドの実行時に、Aliasで指定された名前のユニットのシンボリックリンクを作成する。
** RequiredBy
**: <code>sudo systemctl enable</code>コマンドの実行時に、このユニットの".required"ディレクトリにリンクを作成する。
** WantedBy
**: <code>sudo systemctl enable</code>コマンドの実行時に、このユニットの".wants"ディレクトリにリンクを作成する。
** Also
**: <code>sudo systemctl enable / disable</code>コマンドの実行時に、同時にenable / disableするユニットを記述する。
<br>
ユニットの詳細を知りたい場合は、以下のコマンドを実行する。<br>
man systemd.unit
<br>
サービスの詳細を知りたい場合は、以下のコマンドを実行する。<br>
man systemd.service
<br>
以下に、よく使用されるユニットファイルのフォーマットを示す。<br>
[Unit]
Description=<ユニットファイルの説明>
After=<指定したユニットリストの起動後に実行する>
Before=<指定したユニットリストの前に実行する>
Requires=<指定したユニットリストの起動成功後に実行する。(ユニット起動時に依存ユニットも起動するが、依存ユニット失敗時は起動しない)>
Wants=<指定したユニットリストが起動失敗しても実行する。(ユニット起動時に依存ユニットも起動するが、依存ユニット失敗時でも起動する)>
[Service]
Environment=<環境変数リスト>
EnvironmentFile=<環境変数ファイル>
Type=<simple | forking | oneshot | dbus | notify | idle>
ExecStart=<起動コマンド>
ExecStop=<停止コマンド>
ExecReload=<再起動コマンド>
Restart=<always | on-abort | on-watchdog | on-abnormal | on-failure | on-success | no>
RemainAfterExit=<yes | no>
PIDFile=<メインプロセスのPIDファイルパス>
User=<ユニットファイルの実行ユーザ>
SuccessExitStatus=<(0以外に)メインプロセス正常終了とみなすexitコードリスト>
[Install]
Alias=<ユニットの別名>
RequiredBy=<sudo systemctl enableコマンドの実行時に、このユニットの".required"ディレクトリにリンクを作成する>
WantedBy=<sudo systemctl enableコマンドの実行時に、このユニットの".wants"ディレクトリにリンクを作成する>
Also=<同時に起動および停止するユニット>
<br><br>
== ユニットの依存関係および順序の確認 ==
Systemdユニットの依存関係および順序は、以下のコマンドで確認できる。<br>
<br>
指定したユニットが必要とするユニットを表示する。ユニット名を省略した時は、default.targetが指定される。<br>
依存関係のユニットが<u>Target</u>タイプの場合、さらに、それが必要なユニットを再帰的に表示する。<br>
<code>--all</code>オプションを付加することにより、全てのユニットを再帰的に表示する。<br>
sudo systemctl list-dependencies <ユニット名>
<br>
指定したユニットよりも先に起動するユニットを表示する。<br>
sudo systemctl list-dependencies <ユニット名> --after
<br>
指定したユニットよりも後に起動するユニットを表示する。<br>
sudo systemctl list-dependencies <ユニット名> --before
<br><br>
== ユニットの有効化 / 無効化 ==
指定のユニットを有効化および無効化する。<br>
<br>
maskを使用する場合、<code>sudo systemctl disable</code>と異なり、<code>sudo systemctl start</code>での手動起動もできなくなる。<br>
maskによる無効化は、/etc/systemd/systemディレクトリ下に/dev/nullへのシンボリックリンクを張ることにより行われる。<br>
<br>
また、/etc/systemd/systemディレクトリ下に設定ファイルを作成している場合は、maskによる無効化はできない。<br>
sudo systemctl mask <ユニット名>
# または
sudo systemctl unmask <ユニット名>
<br><br>
== サービスの遅延実行 ==
Systemdサービスを遅延起動する方法には、主に2つの方法がある。<br>
<u>ただし、タイマユニットを使用する方法が一般的であり、より柔軟性が高い。</u><br>
* Systemdのタイマーユニットを使用する方法
* Systemdサービスファイル自体に遅延を設定する方法
<br>
==== タイマユニットを使用する方法 ====
まず、実行するコマンドまたはプログラムを起動するSystemdサービスファイルを作成する。<br>
<syntaxhighlight lang="ini">
[Unit]
Description=My delayed service
[Service]
ExecStart=<実行するコマンドまたはプログラムのパス> [コマンドまたはプログラムのオプション]
</syntaxhighlight>
<br>
次に、特定のSystemdサービスファイルをどのタイミングで起動するかを指定するタイマファイルを作成する。<br>
<syntaxhighlight lang="ini">
[Unit]
Description=Timer for my service
[Timer]
OnBootSec=30      # 30秒後に起動する場合
#OnBootSec=10min  # 10分後に起動する場合
OnUnitActiveSec=24h      # サービスが最後にアクティブになってから24時間後に再びサービスを起動する (繰り返し実行する場合)
Unit=<タイマ起動するsystemdサービスファイル名>
[Install]
WantedBy=timers.target  # タイマをシステムのタイマターゲットに関連付けて、システム起動時にタイマを有効にする
</syntaxhighlight>
<br>
Systemdサービスファイルとタイマファイルを、/etc/systemd/systemディレクトリ、または、~/.config/systemd/userディレクトリに配置する。<br>
Systemdサービスのデーモンを再読み込みする。<br>
# /etc/systemd/systemディレクトリに保存した場合
sudo systemctl daemon-reload
# ~/.config/systemd/userディレクトリに保存した場合
systemctl --user daemon-reload
<br>
タイマサービスを有効または開始する。<br>
これにより、指定時間後にSystemdサービスが自動的に起動するようになる。<br>
# /etc/systemd/systemディレクトリに保存した場合
sudo systemctl enable <タイマファイル名  例: my_service.timer>  # 起動時に開始する場合
sudo systemctl start  <タイマファイル名  例: my_service.timer>  # 通常起動する場合
# ~/.config/systemd/userディレクトリに保存した場合
systemctl --user enable <タイマファイル名  例: my_service.timer>  # 起動時に開始する場合
systemctl --user start  <タイマファイル名  例: my_service.timer>  # 通常起動する場合
<br>
==== Systemdサービスファイル自体に遅延を設定する方法 ====
Systemdサービスファイル内に<code>ExecStartPre</code>キーで時間を指定して、サービスの実行前に遅延 (例: <code>sleep</code>コマンドを使用) を挿入する方法もあるが、この方法は推奨されない。<br>
これは、Systemdのタイマ機能を使用する方法と比較して、柔軟性に欠けることやシステムの起動プロセスを不必要に遅延させる可能性がある。<br>
<br>
そのため、タイマユニットを作成および使用して、サービスの起動タイミングを細かく制御することが推奨される。<br>
<br><br>
== Systemdサービスファイルの構文の確認 ==
Systemdサービスファイル全体の構文を確認する。<br>
これにより、問題のある部分を特定して、修正することができる。<br>
sudo systemd-analyze verify <Systemdサービスファイルまたはタイマファイル等のパス>
<br>
訂正後は、Systemdサービスファイルを再読み込みして、変更を有効にする。<br>
sudo systemctl daemon-reload
# または
systemctl --user daemon-reload
<br><br>
== 独自のユニットやSystemdサービスファイルの作成 ==
例えば、PC起動時に何らかのスクリプトやソフトウェアをバックグラウンドで実行したいとする。<br>
そのためには、サービスユニットを作成する必要がある。<br>
<br>
サービスユニットを作成するための構文を、以下に示す。<br>
<br>
まず、/etc/systemd/systemディレクトリまたは/usr/lib/systemd/systemディレクトリに、ユニットファイルを作成する。<br>
<u>一般的には、ユーザが任意で作成するユニットファイルは、/etc/systemd/systemディレクトリに配置する。</u><br>
sudo vi /usr/lib/systemd/system/<ユニットファイル名>.service
または
sudo vi /etc/systemd/system/<ユニットファイル名>.service
<br>
# スクリプトを使用する場合
[Unit]
Description =          # サービスの説明を記述する
After = network.target  # ※指定しなくてもよい
[Service]
User=              # ユーザ名  例. root  ※指定しなくてもよい
WorkingDirectory=  # 実行するファイルまたはスクリプトがあるディレクトリのフルパス  ※指定しなくてもよい
ExecStart =        # 実行するファイルまたはスクリプトへのフルパス または ファイル名のみ(WorkingDirectoryを指定する場合)
Restart=always    # ※指定しなくてもよい
[Install]
WantedBy =        # multi-user.target または graphical.target等
<br>
# Pythonを使用する場合
[Unit]
Description =          # サービスの説明を記述する
After = network.target  # ※指定しなくてもよい
[Service]
User=              # ユーザ名  例. root  ※指定しなくてもよい
WorkingDirectory=  # 実行する.pyファイルがあるディレクトリのフルパス  ※指定しなくてもよい
ExecStart =        # <Pythonの実行ファイル> <実行する.pyファイルへのフルパス または ファイル名のみ(WorkingDirectoryを指定する場合)>
                    # 例. /usr/bin/python3 main.py
Restart=always    # ※指定しなくてもよい
[Install]
WantedBy =        # multi-user.target または graphical.target等
<br>
以下の例では、Glancesという名前のサービスファイルを作成して、Linux向けの監視ツールであるglancesをバックグラウンドで動作させている。<br>
sudo vi /usr/lib/systemd/system/glances.service
<br>
[Unit]
Description = Glances in Web Server Mode
After = network.target
[Service]
ExecStart = /usr/bin/glances -w -t 5
[Install]
WantedBy = multi-user.target
<br>
<code>[Install]</code>セクションでは、<code>[WantedBy]</code>キーにより、ユニットがいつ起動するかを指定する。<br>
下表に、指定することができるキーの値を示す。<br>
<center>
{| class="wikitable" style="background-color:#fefefe;"
|-
! style="background-color:#66CCFF;" | ターゲット
! style="background-color:#66CCFF;" | 説明
|-
| multi-user.target || グラフィカルログインの有無にかかわらず、マルチユーザシステム用(ランレベル3に対応)
|-
| graphical.target || グラフィカルログインが必要なマルチユーザシステム用(ランレベル3 + グラフィカルログインに対応)
|-
| rescue.target || 一般的に、シングルユーザモードはシステムのレスキュー時にのみ必要(ランレベル1に対応)
|-
| reboot.target || システムの再起動時にのみユニットが実行する。
|-
| poweroff.target || システムのシャットダウン開始時にのみ実行するユニットである。
|-
| default.target || 別の既存ターゲットへのシンボリックリンクである。<br>例えば、Ubuntuデスクトップの初期設定では、default.targetはgraphical.targetである。
|}
</center>
<br>
サービスファイルを読み込んで、新しいサービスを追加する。<br>
sudo systemctl daemon-reload
<br><br>
== 手動で作成したシステムのサービスユニットを有効にする ==
サービスユニットの作成後は、サービスを有効にして起動する必要がある。<br>
<br>
<サービスユニットのファイル名>において、<br>
例えば、上記で作成したglancesサービスを有効にするには、<code>sudo systemctl enable glances.service</code>となる。<br>
<br>
以下のコマンドを実行して、新しいサービスユニットを読み込み・追加する。<br>
sudo systemctl daemon-reload
<br>
サービスユニットを自動起動に設定する。<br>
sudo systemctl enable <サービスユニットのファイル名>
<br>
サービスユニットを起動する。<br>
sudo systemctl start <サービスユニットのファイル名>
<br>
サービスユニットの状態を確認する。<br>
sudo systemctl status <サービスユニットのファイル名>
<br><br>
== Journald ==
Journaldの動作を、以下に示す。<br>
# Rsyslogdへ出力する内容を、systemd-journald.service(Journald)に送信する。
# Journaldはメタ情報を追加して、/var/log/journalディレクトリ下に記録する。
# <code>journalctl</code>コマンドを使用して、Journaldのログ(バイナリ形式)を検索および表示する。
<br>
Systemdは、Rsyslogdの設定変更が必要となる。<br>
* 従来の動作
*: プロセス → /dev/log → Rsyslogd
* Systemd
*: プロセス → /dev/log → Systemd → /run/systemd/journal/syslog → Rsyslogd
<br>
また、Rsyslogdには、Journaldから直接ログ情報を取得するモジュールであるimjournalが存在しており、<br>
UnixSocketである/run/systemd/journal/syslogファイルの代わりに、imjournalを利用することもできる。<br>
<br>
<code>journalctl</code>コマンドの便利なオプションを、以下に示す。<br>
* -aオプション
*: 長いメッセージを省略しない。
* -bオプション
*: 直前のサーバ起動以降のログを表示する。
* -eオプション
*: ページャーで最後にジャンプする。
* -fオプション
*: <code>tail -f</code>コマンドのように、順次表示する。
* -uオプション
*: 指定したユニットのログを表示する。
* -xオプション
*: メッセージの説明がある場合は追加する。
* --since='YYYY-MM-DD hh:mm:ss'
*: 指定日以降のログを表示する。
* --until='YYYY-MM-DD hh:mm:ss'
*: 指定日までのログを表示する。
# 例
sudo journalctl -ex -u <systemdサービスユニット名>
<br><br>
<br><br>


__FORCETOC__
__FORCETOC__
[[カテゴリ:CentOS]][[カテゴリ:SUSE]][[カテゴリ:Raspberry_Pi]][[カテゴリ:PinePhone]]
[[カテゴリ:RHEL]][[カテゴリ:SUSE]][[カテゴリ:Raspberry_Pi]][[カテゴリ:PinePhone]]