Systemdのユニットファイルを編集する際に、謎を感じる挙動があったのでメモ。
ユニットファイルの編集
インストール済みのパッケージが提供する既定のユニットファイルを編集するには、以下の手順を踏むことになっている。
- /usr/lib/systemd/system 配下にあるユニットファイルを /etc/systemd/system にコピーし、そのファイルを編集する。
- 設定を反映するために
systemctl daemon-reload
を実行する。
以前、DHCPサーバを立ち上げた時にも同じような手順でユニットファイルを編集したことがあり、RedHatの公式でもこの手順が案内されている。
この手順については、「/etc/systemd/system 配下にあるユニットファイルが、/usr/lib/systemd/system 配下にあるユニットファイルよりも優先して読み込まれる」、という説明でなんとなく納得した気になっていた。
しかし、Systemdでデーモンを自動起動する仕組みを考えると、何かが足りない気がしてくる。
デーモンが自動起動する流れ
例えば、SSHのデーモン(sshd)は、multi-user.target と依存関係のあるサービスであり、systemctl enable sshd
を実行すると、/etc/systemd/system/multi-user.target.wants 配下に sshd.service へのシンボリックリンクが作られる。
# systemctl enable sshd
Created symlink from /etc/systemd/system/multi-user.target.wants/sshd.service to /usr/lib/systemd/system/sshd.service.
OS起動時には、この multi-user.target.wants 内のユニットファイルで指定されたサービスなどが順次起動していく。これがSystemdによる自動起動の大雑把な仕組みである。
そこで気づくのが、先のユニットファイルの編集方法では、wantsディレクトリ内のシンボリックリンクを変更していないということ。
実際に確かめてみても、リンク先は変わっていないことがわかる。
初期状態のシンボリックリンク↓
[root@sandstone ~]# ls -l /etc/systemd/system/multi-user.target.wants/sshd.service
lrwxrwxrwx. 1 root root 36 5月 14 14:03 /etc/systemd/system/multi-user.target.wants/sshd.service -> /usr/lib/systemd/system/sshd.service
↑/usr/lib/systemd/system 配下を指している。
↓ユニットファイルをコピーして設定をリロード。
[root@sandstone ~]# cp /usr/lib/systemd/system/sshd.service /etc/systemd/system/
[root@sandstone ~]# systemctl --system daemon-reload
↓改めてリンク先を確認。
[root@sandstone ~]# ls -l /etc/systemd/system/multi-user.target.wants/sshd.service
lrwxrwxrwx. 1 root root 36 5月 14 14:03 /etc/systemd/system/multi-user.target.wants/sshd.service -> /usr/lib/systemd/system/sshd.service
↑リンク先は変わっていない。
これでは、自動起動に使われるユニットファイルは、既定の場所(/usr/lib/systemd/system)にあるもののままなのではないか?と思いきや、この状態でOSを再起動すると、ちゃんと /etc/systemd/system 配下のユニットファイルを使ってsshdが起動してくる。
[root@sandstone ~]# systemctl status sshd
● sshd.service - OpenSSH server daemon
Loaded: loaded (/etc/systemd/system/sshd.service; enabled; vendor preset: enabled)
: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
: ↑コピーしたユニットファイルが読み込まれている
ということは、このwantsディレクトリ、別にユニットファイルへのシンボリックリンクを貼る必要はなくて、単にファイル名(ユニット名)だけわかるようにしておけばいいのでは?という疑問がわく。
実験
物は試しなので、wantsディレクトリからシンボリックリンクを削除し、ファイル名をユニット名にした空のファイルと置き換えてみた。
↓既存のシンボリックリンクを削除
[root@sandstone multi-user.target.wants]# rm sshd.service
rm: シンボリックリンク `sshd.service' を削除しますか? y
↓空のファイルを作成
[root@sandstone multi-user.target.wants]# touch sshd.service
[root@sandstone multi-user.target.wants]# ls -l sshd.service
-rw-r--r--. 1 root root 0 5月 14 14:35 sshd.service
この状態でOSを再起動してみると、何事もなかったかのようにsshdは起動してくれた。
これがSystemdの仕様動作なのだろうか?
systemctl がシンボリックリンクを作成するのは、人間が見た時にどのユニットファイルが読み込まれているか把握しやすくするためだけなのか?謎である。
コメント