ここ数週間 systemd について学んできたので、トピックごとにまとめておきます。

第一回目は、OS起動時に systemd で実行される default.target を起点とした依存関係のツリーについてです。

なお、本記事の内容は Ubuntu 16.04, Debian Stretch で動作確認しています。

systemctl list-dependencies

まずはおもむろに sudo systemctl list-dependencies を実行してみましょう!

image.png

default.target を起点として、それから要求される形でどのようなユニットが起動されたかが見られます。緑は成功、赤は失敗、白はその他(依存関係が満たされず、起動されなかった、など)です。

他のことは忘れて良いので、今回、このコマンドだけでも覚えて帰ってください!

default.target とは?

default.target とは、OS の起動シーケンスの起点となるユニットで、systemd は default.target に記述されている依存関係を満たすように、各種ユニットを立ちあげます。

defualt.target の実体はシンボリックリンクで、具体的な処理の中身はリンク先のターゲットによって定められています。

default.target に紐づくターゲットとは?

一般には、GUI のシステムでは graphical.target に、GUI 無しのシステムでは multi-user.target に紐付いています。

default.target に何が紐付いているかは systemctl get-default で確認できます。

$ systemctl get-default
graphical.target

また、 systemctl set-default によって default.target に紐づくターゲットを変更できます。

$ sudo systemctl set-default multi-user.target
Removed symlink /etc/systemd/system/default.target.
Created symlink from /etc/systemd/system/default.target to /lib/systemd/system/multi-user.target.

graphical.target の中身は?

multi-user.target + display-manager.service です。マルチユーザ環境の構築をしつつ、 display manager を立ちあげます。

詳しく知りたい人は graphical.target の中身を読んでみてください。

$ cat /lib/systemd/system/graphical.target

multi-user.target は何をするのか?

multi-user.target は複数ユーザ環境のベースとなるターゲットで、多くのサービスがこのターゲットに紐付いて起動されます。

multi-user.target 自身で指定されている依存関係は basic.target への Requires だけですが、外部のユニットから指定された multi-user.target.wants が重要です。

  • /lib/systemd/system/multi-user.target.wants/
  • /etc/systemd/system/multi-user.target.wants/

これらのディレクトリの下に multi-user.target に依存するユニットのシンボリックリンクが置かれており、これらが集まって multi-user.target を起点とした依存関係のグラフが形成され、OS 起動時に実行されるわけです。

どうやってユニットを multi-user.target に紐付けるのか?

systemd で管理された各種ユニットは、定義ファイルに

[Install]
WantedBy=multi-user.target

のように記述することで、multi-user.target の起動時に一緒に起動するよう、要求することができます。

なお、この記述だけがあっても自動起動はしません。systemctl enable <unit> コマンドで有効にして初めて、 multi-user.target.wants にシンボリックリンクが生成され、 multi-user.target の実行時にユニットがあわせて起動されるようになります。

また systemctl disable <unit> をすれば、シンボリックリンクが削除されて、 multi-user.target の依存関係のグラフからユニットが外されます。

ただし、enable にしていても、依存ツリーの中で自身が要求されなければ起動されないですし、disable であっても、何かしらのルートで要求があると起動します。このあたりの依存関係のルールの詳細は、別の記事で説明しようと思います。

「起動にかかった時間」とは?

「OSの起動にかかる時間」とは、「defualt.target の依存関係ツリーを立ち上げるのにかかった時間」とほぼ同じ意味で、 systemd-analyze コマンドで確認できます。

$ sudo systemd-analyze
Startup finished in 5.483s (firmware) + 4.044s (loader) + 1.658s (kernel) + 6.310s (userspace) = 17.496s

同様のログは、journalctl にも記録されています。

$ sudo journalctl -b
...
Apr 11 14:07:24 somehost systemd[1]: Reached target Multi-User System.
Apr 11 14:07:24 somehost systemd[1]: Reached target Graphical Interface.
Apr 11 14:07:24 somehost systemd[1]: Starting Update UTMP about System Runlevel Changes...
Apr 11 14:07:24 somehost systemd[1]: Started Update UTMP about System Runlevel Changes.
Apr 11 14:07:24 somehost systemd[1]: Startup finished in 2.185s (kernel) + 9.827s (userspace) = 29.116s.
...

default.target にカスタムのターゲットを紐付けたい

この仕組みを利用すれば、カスタムのターゲットも簡単に作成できます。

graphical.target を参考にするのが良いでしょう。

例えば、自社ロボット専用の起動シーケンスを作りたい場合、下記のようなターゲットを作り、

$ cat /lib/systemd/system/robot.target
[Unit]
Description=Robot Mode
Requires=multi-user.target
Conflicts=rescue.service rescue.target
After=multi-user.target rescue.service rescue.target
AllowIsolate=yes

起動時に立ちあげたい systemd のユニットに

[Install]
WantedBy=robot.target

のような依存関係を定義し、

sudo systemctl set-default robot.target

を実行すれば、OS起動時に自動でユニットを立ちあげられるようになります。また、

sudo systemctl set-default multi-user.target

などとすれば、元の起動シーケンスに戻せます。

AllowIsolate とは何か?

AllowIsolate や有効になっているユニットは、 systemctl isolate コマンドで起動することができます。systemctl isolate コマンドでターゲットを起動すると、 指定したターゲットが(明示的に)依存するユニット以外は全て停止してから、ターゲットが起動されます。set-default で指定するターゲットは、基本的には AllowIsolate が指定されたターゲットです。

ただし、下記の Issue で議論されているように、 systemctl isolate が実行された瞬間に、 明示的に 定義されている依存関係以外はいったんすべて終了してしまうので、モードの切替に systemctl isolate コマンドは使いづらいです。例えば robot.target に切り替えたい場合、 set-default してからシステムを再起動する方が確実です。

関連資料

全体の体系としては分かりづらいですが、個々の仕様を確認するには systemd のオンラインマニュアルが有用です。

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.