【Linux】【systemd】systemd について(詳細編)

systemd についてのまとめ。
Redhat の RHEL 7 における systemd の概要を説明を実践しつつ確認する。
主に LPIC 201 受験のために暗記学習したが、ほとんど忘却していたのでまとめ直す。
なお、細部まで確認しているが、実際、それほど見ることはないかと思われる。

 

概念

systemd とは

systemdでは、「Unit」という単位で処理を管理します。

これまで、rc.sysinitやサービス起動スクリプトが実施していた処理の内容は、
すべて、Unitとして定義されます。

Unitは、「target」「mount」「service」「device」など、役割によってタイプがわかれています。

それぞれのUnitは、依存関係が定義されており、PID=1の最初のプロセスとしてsystemdが
起動すると、「default.target」というUnitを頂点とする、依存関係のツリーを構築した後、
依存するUnitを起動していきます。
http://enakai00.hatenablog.com/entry/20130914/1379146157

 

/sbin/init の実体を確認する

f:id:dnkrnka:20171125141212p:plain
init は systemd へのシンボリックリンクになっている↓

% pgrep -fln journal
22662 journalctl
% which init
/sbin/init
% ls -l /sbin/init
lrwxrwxrwx 1 root root 20  421 01:55 /sbin/init -> /lib/systemd/systemd*

 

journalctlを確認する

ロギングに関しては、/run 以下にログが残っており、journalctl コマンドでも表示できる。
f:id:dnkrnka:20171125142435p:plain

% ls -ltr /run
合計 28
drwxr-xr-x  4 root  root   120  929  2018 NetworkManager/
-rw-r--r--  1 root  root     4  929  2018 acpid.pid
srw-rw-rw-  1 root  root     0  929  2018 acpid.socket=
drwxr-xr-x  2 root  root    40  929  2018 alsa/
drwxr-xr-x  2 root  root    60  929  2018 apache2/
drwxr-xr-x  2 avahi avahi   80  929  2018 avahi-daemon/
drwxr-xr-x  2 root  root    80  929  2018 console-setup/
-rw-r--r--  1 root  root     4  929  2018 crond.pid
----------  1 root  root     0  929  2018 crond.reboot
drwxr-xr-x  3 root  lp     100  929 11:22 cups/
drwxr-xr-x  2 root  root    60  929  2018 dbus/
-rw-r--r--  1 root  root     5  929  2018 dhclient-eno1.pid
drwx--x--x  3 root  gdm     60  929  2018 gdm3/
-rw-r--r--  1 root  root     4  929  2018 gdm3.pid
lrwxrwxrwx  1 root  root    25  929  2018 initctl -> /run/systemd/initctl/fifo|
drwxr-xr-x  2 root  root    80  929  2018 initramfs/
drwxrwxrwt  4 root  root   100  929  2018 lock/
drwxr-xr-x  2 root  root    40  929  2018 log/
-rw-r--r--  1 root  root     0  929 11:22 mlocate.daily.lock
drwxr-xr-x  2 root  root    80  929  2018 mount/
drwxr-xr-x  2 root  root   100  929  2018 network/
drwxr-xr-x  2 root  root    40  929  2018 plymouth/
drwxr-xr-x  2 root  root    40  929  2018 pppconfig/
drwxr-xr-x  3 root  root   100  929  2018 resolvconf/
-rw-r--r--  1 root  root     3  929  2018 rsyslogd.pid
drwxr-xr-x  2 root  root    40  929  2018 sendsigs.omit.d/
lrwxrwxrwx  1 root  root     8  929  2018 shm -> /dev/shm/
srw-rw-rw-  1 root  root     0  929  2018 snapd-snap.socket=
srw-rw-rw-  1 root  root     0  929  2018 snapd.socket=
drwxr-xr-x  2 root  root    40  929  2018 spice-vdagentd/
drwxr-xr-x  2 root  root    40  929  2018 sshd/
-rw-r--r--  1 root  root     4  929  2018 sshd.pid
drwx--x--x  3 root  root    60  929  2018 sudo/
drwxr-xr-x 20 root  root   460  929  2018 systemd/
drwxr-xr-x  2 root  root    60  929  2018 thermald/
drwxr-xr-x  2 root  root    60  929  2018 tmpfiles.d/
drwxr-xr-x  7 root  root   160  929 11:34 udev/
drwx------  2 root  root    40  929  2018 udisks2/
drwxr-xr-x  4 root  root    80  929  2018 user/
-rw-rw-r--  1 root  utmp  1152  929  2018 utmp
drwxr-xr-x  2 root  root    60  929  2018 uuidd/
drwxr-x---  2 root  root    60  929 11:34 wpa_supplicant/
drwxr-xr-x  3 xrdp  xrdp   100  929  2018 xrdp/
% ls -l /var/log/journal
合計 4
drwxr-sr-x+ 2 root systemd-journal 4096  929 11:17 d2e90f9e163b4a7aa5a46d590f97b41f/

% s -l /var/log/journal/d2e90f9e163b4a7aa5a46d590f97b41f
(--snip--)
-rw-r-----+ 1 root systemd-journal  25165824  929  2018 'user-1000@3dc4a26319d341fe96ca4c3330d10fc0-000000000003f857-000574197a1a4590.journal'
-rw-r-----+ 1 root systemd-journal   8388608  929 11:17 'user-1000@3dc4a26319d341fe96ca4c3330d10fc0-0000000000058bf0-00057700b8032b60.journal'
-rw-r-----+ 1 root systemd-journal   8388608  520 13:04 'user-1000@e32e5c05c3e542c8b2fa27837affef49-00000000000004d6-00056c8fd825f4da.journal'
-rw-r-----+ 1 root systemd-journal   8388608  56 02:49  user-65534.journal

 

journalctl -k -e で dmesg の詳細相当を表示する

journalctl -k -e コマンド(dmesgの詳細版相当)でも /run 以下のログを参照している。
journalctl が参照しているファイルは以下で確認することができる。
 

journalctl がアクセスしているファイルを洗い出す

1. journalctl を実行する

% journalctl -ke
(Ctrl-z でバックグラウンドに回す)

 
2. journalctl コマンドのプロセス番号を取得する

% pgrep -fln journal
22662 journalctl

 
3. lsof -p [journalctlプロセス番号] を使ってアクセスしているファイルを洗い出す

% lsof -p 22662
(--snip--)

 

依存関係

f:id:dnkrnka:20180929133819p:plain:w1000
 
いわゆる、ユニット、ターゲットの話。
 

ユニット

SystemV での /etc/rc.d/rc.sysinit や /etc/init.d/* の処理に相当する。
ユニット内ではさらに swap, socket, device, service・・・ といったように区分けされている。
f:id:dnkrnka:20171125211822p:plain

systemctl list-units を実行することで以下の通りユニットが存在していることが分かる。

% systemctl list-units | awk '{print $1}' | sed -n 's/\(.*\)\.\(.*\)/\2/p'|awk '{print $1}' | sort -u
automount
device
mount
path
scope
service
slice
socket
swap
target
timer

 
ユニットファイル = systemd の設定ファイルであり、システム用とユーザ定義用の2つに分かれている。 

システム用 ( /lib/systemd/system )

正確なパスについては、pkg-config systemd --variable=systemdsystemunitdir で確認すること。

% pkg-config systemd --variable=systemdsystemunitdir
/lib/systemd/system
ユーザ定義用 ( /etc/systemd/system )

正確なパスについては、pkg-config systemd --variable=systemduserunitdir で確認すること。

% pkg-config systemd --variable=systemduserunitdir
/usr/lib/systemd/user

 

ターゲット

SystemV のランレベルに相当する概念である。
SystemV では /etc/inittab で起動時のランレベルを定義していたが、systemd では各ターゲットファイルにて依存関係が書かれている。
目視でその依存関係を辿ることは大変なので、次のように systemctl list-dependencies コマンドで確認すれば良い。
 

ターゲットの依存関係を表示する

現在、起動時に実行される target を確認する

% systemctl list-dependencies default.target --after |grep -F -e ".target"
default.target
● ├─multi-user.target
● │ ├─basic.target
● │ │ ├─paths.target
● │ │ ├─slices.target
● │ │ ├─sockets.target
● │ │ └─sysinit.target
● │ │   ├─cryptsetup.target
● │ │   ├─emergency.target
● │ │   ├─local-fs.target
● │ │   │ └─local-fs-pre.target
● │ │   └─swap.target
● │ ├─getty.target
● │ └─rescue.target
● │   └─sysinit.target
● │     ├─cryptsetup.target
● │     ├─emergency.target
● │     ├─local-fs.target
● │     │ └─local-fs-pre.target
● │     └─swap.target
● └─rescue.target
●   └─sysinit.target
●     ├─cryptsetup.target
●     ├─emergency.target
●     ├─local-fs.target
●     │ └─local-fs-pre.target
●     └─swap.target

 
 

cgroups

f:id:dnkrnka:20171125151504p:plain

cgroups とはサイオス様のページを参照。以下、実質、メモ代わりに転記をしているだけである。

  • 「プロセスをグループ化して、リソースの利用をコントロール」するカーネル機能である。
  • グループ単位でリソースの割り当て、優先度、管理、モニタリングなどが設定できる。
  • cgroups そのものはプロセスを「コントロールグループ」と呼ばれる単位にまとめるのみ。
  • リソースコントロールを行うにはコントロールグループに「サブシステム」と呼ばれる抽象化されたリソース群をつなげる必要がある。
    • f:id:dnkrnka:20171125210642p:plain
%  cat /proc/cgroups 
#subsys_name	hierarchy	num_cgroups	enabled
cpuset	6	1	1
cpu	7	1	1
cpuacct	7	1	1
blkio	10	1	1
memory	8	1	1
devices	5	49	1
freezer	3	1	1
net_cls	2	1	1
perf_event	9	1	1
net_prio	2	1	1
hugetlb	4	1	1
pids	12	55	1
rdma	11	1	1

f:id:dnkrnka:20171125211630p:plain

cat /proc/cgroups の第1フィールドである。上述の cgroup で記した「サブシステム」を参照。
 

リソース管理

f:id:dnkrnka:20171125215927p:plain

libcgroup のインストールが必要。詳細はこちらもサイオス様のページを参照。
 
 



起動処理について

default.target の読み込み

f:id:dnkrnka:20171125233930p:plain

systemd は最初に default.target を読み込む。
default.target は SystemV のランレベルに相当する target ファイルへのリンクである。
 

default.target の実体

default.target の実体は systemctl get-default で調べられる。

% systemctl get-default
graphical.target

 

default.target ファイルのありか

default.target の置き場は systemd 導入時の設定により異なるので、まずは systemd の設定ファイル置き場を調べると良い。

% pkg-config systemd --variable=systemdsystemunitdir
/lib/systemd/system

そして find コマンドで /lib/systemd/system 以下を探す。

% find /lib/systemd/system -name "default.target" -ls
 (--snip--) /lib/systemd/system/default.target -> graphical.target

 

default.target から graphical.target の呼び出し

f:id:dnkrnka:20171126002118p:plain:w1000

  • Requires=multi-user.target
    • 本ユニットが必要とする前提ユニット。
    • Requires で定義したユニットが失敗すると、本ユニットの実行は行われない。
  • Wants=display-manager.service
    • 本ユニットが必要とする前提ユニット。
    • Wants で定義したユニットが失敗しても、本ユニットの実行は行われる
    • 「Wants=」を書かない代わりに「サービス名.wants」というフォルダに前提ユニットファイルを置けば同じ挙動になる。
      • この場合であれば、/lib/systemd/system/default.target.wants/display-manager.service ということである。
      • ただし、システム上必須の依存関係は「Requires=」「Wants=」に記載し、システム管理者が+αで設定する依存関係は「サービス名.wants」を使うのが一般的。
  • Conflicts=rescue.service rescue.target
    • 同時に実行してはいけないユニット
  • After=multi-user.target rescue.service rescue.target display-manager.service
    • 本ユニットは「After」で書かれたユニットが完了するまで実行しない、ということ。
    • ここでは 「multi-user.target」 「rescue.service」 「rescue.target」 「display-manager.service」 の4つが完了するまで本ユニットは実行されない。
  • Before=XXXX.target
    • 本ユニットは「Before」で書かれたユニットよりも先に実行するということ。
  • AllowIsolate=yes
    • yes (真)であれば、一時的な設定(isolate)が使えるということ。
      • 例:一時的に GUI モードで起動させる。
        • systemctl isolate graphical.target
      • 例:一時的に CUI モードで起動させる。
        • systemctl isolate multi-user.target



graphical.target から multi-user.target の呼び出し

f:id:dnkrnka:20171126011949p:plain

上図赤線と同様に私の環境でも「Requires=basic.target」がある。

% cat /lib/systemd/system/multi-user.target
[Unit]
Description=Multi-User System
Documentation=man:systemd.special(7)
Requires=basic.target
Conflicts=rescue.service rescue.target
After=basic.target rescue.service rescue.target
AllowIsolate=yes

上図緑線と同様に multi-user.target.wants ディレクトリ以下のファイルが開始する。

現在時刻は 2017年11月24日であるが、「multi-user.target.wants」(以下「wantsディレクトリ」)から本体へのシンボリックリンクが生成した時刻は2ヶ月以上前のものが多い。

つまり、systemctl でシステムの ON・OFF を切り替えない限りは wantsディレクトリから出るシンボリックリンクは消えないものと推測される。(上図紫線)

% ls -l /lib/systemd/system/multi-user.target.wants/
合計 0
lrwxrwxrwx 1 root root 15 1116  2017 dbus.service -> ../dbus.service
lrwxrwxrwx 1 root root 15  721 02:13 getty.target -> ../getty.target
lrwxrwxrwx 1 root root 29  413 09:07 plymouth-quit-wait.service -> ../plymouth-quit-wait.service
lrwxrwxrwx 1 root root 24  413 09:07 plymouth-quit.service -> ../plymouth-quit.service
lrwxrwxrwx 1 root root 33  721 02:13 systemd-ask-password-wall.path -> ../systemd-ask-password-wall.path
lrwxrwxrwx 1 root root 25  721 02:13 systemd-logind.service -> ../systemd-logind.service
lrwxrwxrwx 1 root root 39  721 02:13 systemd-update-utmp-runlevel.service -> ../systemd-update-utmp-runlevel.service
lrwxrwxrwx 1 root root 32  721 02:13 systemd-user-sessions.service -> ../systemd-user-sessions.service

 
ユーザ定義用置き場には、システム用へのシンボリックリンクが貼られている。

% ls -l /etc/systemd/system/multi-user.target.wants/
合計 0
lrwxrwxrwx 1 root root 40  56 01:45 ModemManager.service -> /lib/systemd/system/ModemManager.service
lrwxrwxrwx 1 root root 42  56 01:45 NetworkManager.service -> /lib/systemd/system/NetworkManager.service
lrwxrwxrwx 1 root root 35  56 01:45 anacron.service -> /lib/systemd/system/anacron.service
lrwxrwxrwx 1 root root 35  512 15:29 apache2.service -> /lib/systemd/system/apache2.service
lrwxrwxrwx 1 root root 40  56 01:45 avahi-daemon.service -> /lib/systemd/system/avahi-daemon.service
lrwxrwxrwx 1 root root 42  56 22:01 binfmt-support.service -> /lib/systemd/system/binfmt-support.service
lrwxrwxrwx 1 root root 37  56 01:45 cgmanager.service -> /lib/systemd/system/cgmanager.service
lrwxrwxrwx 1 root root 35  56 01:45 cgproxy.service -> /lib/systemd/system/cgproxy.service
lrwxrwxrwx 1 root root 46  56 01:45 click-system-hooks.service -> /lib/systemd/system/click-system-hooks.service
lrwxrwxrwx 1 root root 32  56 01:45 cron.service -> /lib/systemd/system/cron.service
lrwxrwxrwx 1 root root 40  56 01:45 cups-browsed.service -> /lib/systemd/system/cups-browsed.service
lrwxrwxrwx 1 root root 29  56 01:45 cups.path -> /lib/systemd/system/cups.path
lrwxrwxrwx 1 root root 37  56 01:45 dns-clean.service -> /lib/systemd/system/dns-clean.service
lrwxrwxrwx 1 root root 38  56 02:41 irqbalance.service -> /lib/systemd/system/irqbalance.service
lrwxrwxrwx 1 root root 38  56 02:47 kerneloops.service -> /lib/systemd/system/kerneloops.service
lrwxrwxrwx 1 root root 38  519 23:12 lm-sensors.service -> /lib/systemd/system/lm-sensors.service
lrwxrwxrwx 1 root root 47  56 03:53 networkd-dispatcher.service -> /lib/systemd/system/networkd-dispatcher.service
lrwxrwxrwx 1 root root 38  56 01:45 networking.service -> /lib/systemd/system/networking.service
lrwxrwxrwx 1 root root 36  56 01:45 ondemand.service -> /lib/systemd/system/ondemand.service
lrwxrwxrwx 1 root root 35  56 01:45 openvpn.service -> /lib/systemd/system/openvpn.service
lrwxrwxrwx 1 root root 36  56 01:45 pppd-dns.service -> /lib/systemd/system/pppd-dns.service
lrwxrwxrwx 1 root root 36  56 01:45 remote-fs.target -> /lib/systemd/system/remote-fs.target
lrwxrwxrwx 1 root root 33  56 02:39 rsync.service -> /lib/systemd/system/rsync.service
lrwxrwxrwx 1 root root 35  56 01:45 rsyslog.service -> /lib/systemd/system/rsyslog.service
lrwxrwxrwx 1 root root 40  91 01:17 snap-core-5328.mount -> /etc/systemd/system/snap-core-5328.mount
lrwxrwxrwx 1 root root 38  91 01:18 snap-go-2635.mount -> /etc/systemd/system/snap-go-2635.mount
lrwxrwxrwx 1 root root 44  56 02:48 snapd.autoimport.service -> /lib/systemd/system/snapd.autoimport.service
lrwxrwxrwx 1 root root 41  56 01:45 snapd.boot-ok.service -> /lib/systemd/system/snapd.boot-ok.service
lrwxrwxrwx 1 root root 44  56 02:48 snapd.core-fixup.service -> /lib/systemd/system/snapd.core-fixup.service
lrwxrwxrwx 1 root root 43  56 01:45 snapd.firstboot.service -> /lib/systemd/system/snapd.firstboot.service
lrwxrwxrwx 1 root root 33  56 01:45 snapd.service -> /lib/systemd/system/snapd.service
lrwxrwxrwx 1 root root 31  512 16:09 ssh.service -> /lib/systemd/system/ssh.service
lrwxrwxrwx 1 root root 35  61 06:09 sysstat.service -> /lib/systemd/system/sysstat.service
lrwxrwxrwx 1 root root 44  56 01:45 systemd-resolved.service -> /lib/systemd/system/systemd-resolved.service
lrwxrwxrwx 1 root root 36  56 01:45 thermald.service -> /lib/systemd/system/thermald.service
lrwxrwxrwx 1 root root 31  56 01:45 ufw.service -> /lib/systemd/system/ufw.service
lrwxrwxrwx 1 root root 47  56 02:49 unattended-upgrades.service -> /lib/systemd/system/unattended-upgrades.service
lrwxrwxrwx 1 root root 42  56 03:48 wpa_supplicant.service -> /lib/systemd/system/wpa_supplicant.service
lrwxrwxrwx 1 root root 39  520 16:49 xrdp-sesman.service -> /lib/systemd/system/xrdp-sesman.service
lrwxrwxrwx 1 root root 32  520 16:49 xrdp.service -> /lib/systemd/system/xrdp.service

 

multi-user.target から basic.target の呼び出し

f:id:dnkrnka:20171126013859p:plain
上図の通り「Requires=sysinit.target」とあり、sysinit.target の成功終了に依存している。
下記の「RequiresMountsFor=/var /var/tmp」の意味について。
「Requires=〜」が完遂した
「Wants=〜」が終了した
という2つの条件を満たしたら 「/var と /var/tmp」のマウント完了を待つという意味である。

% cat /lib/systemd/system/basic.target 
[Unit]
Description=Basic System
Documentation=man:systemd.special(7)
Requires=sysinit.target
Wants=sockets.target timers.target paths.target slices.target
After=sysinit.target sockets.target paths.target slices.target tmp.mount
RequiresMountsFor=/var /var/tmp
Wants=tmp.mount

上記の「After=」にある「sockets.target」から「sockets.target.wants/dbus.socket」が呼び出されて、D-Bus*1の設定が行われている。以下に転載する。

% cat /lib/systemd/system/sockets.target.wants/dbus.socket
[Unit]
Description=D-Bus System Message Bus Socket

[Socket]
ListenStream=/var/run/dbus/system_bus_socket


systemd-udevd-kernel.socket はカーネルオブジェクトの読み込みをするユニットファイルであり、さらに「Service=systemd-udevd.service」につながる。

% cat /lib/systemd/system/sockets.target.wants/systemd-udevd-kernel.socket  

[Unit]
Description=udev Kernel Socket
Documentation=man:systemd-udevd.service(8) man:udev(7)
DefaultDependencies=no
Before=sockets.target
ConditionPathIsReadWrite=/sys

[Socket]
Service=systemd-udevd.service
ReceiveBuffer=128M
ListenNetlink=kobject-uevent 1
PassCredentials=yes

「Service=systemd-udevd.service」は以下であり、「ExecStart=/lib/systemd/systemd-udevd」が uevent (デバイス接続検知イベント)を待つ。

% cat /lib/systemd/system/systemd-udevd.service

[Unit]
Description=udev Kernel Device Manager
Documentation=man:systemd-udevd.service(8) man:udev(7)
DefaultDependencies=no
Wants=systemd-udevd-control.socket systemd-udevd-kernel.socket
After=systemd-udevd-control.socket systemd-udevd-kernel.socket systemd-sysusers.service
Before=sysinit.target
ConditionPathIsReadWrite=/sys

[Service]
Type=notify
OOMScoreAdjust=-1000
Sockets=systemd-udevd-control.socket systemd-udevd-kernel.socket
Restart=always
RestartSec=0
ExecStart=/lib/systemd/systemd-udevd
KillMode=mixed
WatchdogSec=3min
TasksMax=infinity
MountFlags=slave
MemoryDenyWriteExecute=yes
RestrictRealtime=yes
RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6


 

basic.target から sysinit.target の呼び出し

f:id:dnkrnka:20171126014150p:plain

% cat /lib/systemd/system/sysinit.target

[Unit]
Description=System Initialization
Documentation=man:systemd.special(7)
Conflicts=emergency.service emergency.target
Wants=local-fs.target swap.target
After=local-fs.target swap.target emergency.service emergency.target



sysinit.target から local-fs.target の呼び出し

local-fs-pre.target は実質処理は無いが、「local-fs-pre.target.wants ディレクトリ」に fsck などがある。

% cat /lib/systemd/system/local-fs.target |grep -v '#'
[Unit]
Description=Local File Systems
Documentation=man:systemd.special(7)
DefaultDependencies=no
Conflicts=shutdown.target
After=local-fs-pre.target
OnFailure=emergency.target
OnFailureJobMode=replace-irreversibly



local-fs.target.wants/systemd-remount-fs.service の呼び出し


f:id:dnkrnka:20171126025456p:plain

依存関係はもう少し続くが、本ユニットファイルでは以下の処理をしている。
# initramfs からネットワーク設定をインポートする
# (必要に応じて) root ファイルシステムで ファイルシステムチェック (fsck) を実行する
# /etc/fstab ファイルのコンテンツに基づいて root ファイルシステム (および特殊なカーネルファイルシステム) を再マウントする。

該当する箇所は以下である。関連ファイルの中身を後述しておく。

  • 「After=systemd-fsck-root.service」
    • /lib/systemd/system/systemd-fsck-root.service
      • /lib/systemd/systemd-fsck コマンド実行している。*2
  • 「ExecStart=/lib/systemd/systemd-remount-fs」
% cat /lib/systemd/system/local-fs.target.wants/systemd-remount-fs.service
[Unit]
Description=Remount Root and Kernel File Systems
Documentation=man:systemd-remount-fs.service(8)
Documentation=http://www.freedesktop.org/wiki/Software/systemd/APIFileSystems
DefaultDependencies=no
Conflicts=shutdown.target
After=systemd-fsck-root.service
Before=local-fs-pre.target local-fs.target shutdown.target
Wants=local-fs-pre.target
ConditionPathExists=/etc/fstab

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/lib/systemd/systemd-remount-fs

 

emregency.target の呼び出し

System V init では無かったランレベルで緊急用らしい。
後述の「emergency.service」を見ると、「echo -e 〜〜」として緊急レベルでの再起動を促していることが分かる。

[neko@PC-Vostro-230 /etc/systemd]$ cat /lib/systemd/system/emergency.target

[Unit]
Description=Emergency Mode
Documentation=man:systemd.special(7)
Requires=emergency.service
After=emergency.service
AllowIsolate=yes
% cat /lib/systemd/system/emergency.service
[Unit]
Description=Emergency Shell
Documentation=man:sulogin(8)
DefaultDependencies=no
Conflicts=shutdown.target
Conflicts=rescue.service
Conflicts=syslog.socket
Before=shutdown.target

[Service]
Environment=HOME=/root
WorkingDirectory=-/root
ExecStartPre=-/bin/sh -c "[ -x /bin/plymouth ] && /bin/plymouth --wait quit"
ExecStartPre=-/bin/echo -e 'You are in emergency mode. After logging in, type "journalctl -xb" to view\\nsystem logs, "systemctl reboot" to reboot, "systemctl default" or ^D to\\ntry again to boot into default mode.'
ExecStart=-/bin/sh -c "/sbin/sulogin; /bin/systemctl --job-mode=fail --no-block default"
Type=idle
StandardInput=tty-force
StandardOutput=inherit
StandardError=inherit
KillMode=process
IgnoreSIGPIPE=no
SendSIGHUP=yes


以上より、長くなったが *.target ファイルが System V init の各ランレベルに該当していることが判明した。(詳細は次)

以下はおまけ。依存関係を systemctl コマンドで表示した結果である。
 
 

おまけ

emergency.target が開始するまでに完遂が必要なサービス一覧
% systemctl list-dependencies emergency.target --after 

emergency.target
● └─emergency.service



local-fs.target が開始するまでに完遂が必要なサービス一覧
% systemctl list-dependencies local-fs.target --after

local-fs.target
● ├─-.mount
● ├─boot.mount
● ├─run-user-1000-gvfs.mount
● ├─run-user-1000.mount
● ├─systemd-fsck-root.service
● ├─systemd-quotacheck.service
● ├─systemd-remount-fs.service
● └─local-fs-pre.target
●   ├─dm-event.service
●   ├─friendly-recovery.service
●   ├─keyboard-setup.service
●   ├─lvm2-monitor.service
●   ├─systemd-remount-fs.service
●   └─systemd-tmpfiles-setup-dev.service

 

sysinit.target が開始するまでに完遂が必要なサービス一覧
% systemctl list-dependencies sysinit.target --after

sysinit.target
● ├─apparmor.service
● ├─dev-hugepages.mount
● ├─dev-mqueue.mount
● ├─emergency.service
● ├─kmod-static-nodes.service
● ├─plymouth-read-write.service
● ├─proc-sys-fs-binfmt_misc.automount
● ├─sys-fs-fuse-connections.mount
● ├─sys-kernel-config.mount
● ├─sys-kernel-debug.mount
● ├─systemd-binfmt.service
● ├─systemd-hwdb-update.service
● ├─systemd-journald.service
● ├─systemd-machine-id-commit.service
● ├─systemd-modules-load.service
● ├─systemd-random-seed.service
● ├─systemd-sysctl.service
● ├─systemd-timesyncd.service
● ├─systemd-tmpfiles-setup-dev.service
● ├─systemd-tmpfiles-setup.service
● ├─systemd-udev-trigger.service
● ├─systemd-udevd.service
● ├─systemd-update-utmp.service
● ├─cryptsetup.target
● │ ├─systemd-ask-password-console.path
● │ └─systemd-ask-password-wall.path
● ├─emergency.target
● │ └─emergency.service
● ├─local-fs.target
● │ ├─-.mount
● │ ├─boot.mount
● │ ├─run-user-1000-gvfs.mount
● │ ├─run-user-1000.mount
● │ ├─systemd-fsck-root.service
● │ ├─systemd-quotacheck.service
● │ ├─systemd-remount-fs.service
● │ └─local-fs-pre.target
● │   ├─dm-event.service
● │   ├─friendly-recovery.service
● │   ├─keyboard-setup.service
● │   ├─lvm2-monitor.service
● │   ├─systemd-remount-fs.service
● │   └─systemd-tmpfiles-setup-dev.service
● └─swap.target
●   ├─dev-disk-by\x2did-dm\x2dname\x2dubuntu\x2d\x2dvg\x2dswap_1.swap
●   ├─dev-disk-by\x2did-dm\x2duuid\x2dLVM\x2dh6dVLlVqh0mPkldM2LvOKPvKxjYevkOgJH…ap
●   ├─dev-disk-by\x2duuid-8b4b6f36\x2d162f\x2d44bc\x2da5db\x2d6129540158fd.swap
●   ├─dev-dm\x2d1.swap
●   ├─dev-mapper-ubuntu\x2d\x2dvg\x2dswap_1.swap
●   └─dev-ubuntu\x2dvg-swap_1.swap

 
 

その他

System V init と systemd の比較

前章の長い長い記述により、*.target が System V init のランレベルに対応していることの裏付けがほぼ取れたので、System V init と Systemd を比較してみる。
下図は SIOS Tech. Lab – エンジニアのためになる技術トピックス より引用した。

f:id:dnkrnka:20171126030907p:plain
 

target の依存関係

default.target から実行される target およびユニット(service, path, socket ...)
% systemctl list-dependencies default.target --after

default.target
● ├─accounts-daemon.service
● ├─apport.service
● ├─gpm.service
● ├─grub-common.service
● ├─irqbalance.service
● ├─lightdm.service
● ├─rescue.service
● ├─speech-dispatcher.service
● ├─stunnel4.service
● ├─multi-user.target
● │ ├─anacron.service
● │ ├─apache2.service
● │ ├─apport.service
● │ ├─avahi-daemon.service
● │ ├─click-system-hooks.service
● │ ├─cron.service
● │ ├─cups-browsed.service
● │ ├─cups.path
● │ ├─dbus.service
● │ ├─gpm.service
● │ ├─grub-common.service
● │ ├─irqbalance.service
● │ ├─libvirt-guests.service
● │ ├─libvirtd.service
● │ ├─ModemManager.service
● │ ├─mysql.service
● │ ├─NetworkManager.service
● │ ├─nmbd.service
● │ ├─ondemand.service
● │ ├─openvpn.service
● │ ├─plymouth-quit-wait.service
● │ ├─plymouth-quit.service
● │ ├─pppd-dns.service
● │ ├─repowerd.service
● │ ├─rescue.service
● │ ├─rsync.service
● │ ├─rsyslog.service
● │ ├─smbd.service
● │ ├─snapd.autoimport.service
● │ ├─snapd.core-fixup.service
● │ ├─snapd.service
● │ ├─speech-dispatcher.service
● │ ├─ssh.service
● │ ├─stunnel4.service
● │ ├─systemd-logind.service
● │ ├─systemd-networkd.service
● │ ├─systemd-resolved.service
● │ ├─systemd-user-sessions.service
● │ ├─thermald.service
● │ ├─unattended-upgrades.service
● │ ├─whoopsie.service
● │ ├─winbind.service
● │ ├─basic.target
● │ │ ├─-.mount
● │ │ ├─systemd-ask-password-plymouth.path
● │ │ ├─tmp.mount
● │ │ ├─paths.target
● │ │ │ ├─acpid.path
● │ │ │ ├─cups.path
● │ │ │ ├─systemd-ask-password-console.path
● │ │ │ └─systemd-ask-password-wall.path
● │ │ ├─slices.target
● │ │ │ ├─-.slice
● │ │ │ ├─system.slice
● │ │ │ └─user.slice
● │ │ ├─sockets.target
● │ │ │ ├─acpid.socket
● │ │ │ ├─apport-forward.socket
● │ │ │ ├─avahi-daemon.socket
● │ │ │ ├─cups.socket
● │ │ │ ├─dbus.socket
● │ │ │ ├─pcscd.socket
● │ │ │ ├─snapd.socket
● │ │ │ ├─syslog.socket
● │ │ │ ├─systemd-initctl.socket
● │ │ │ ├─systemd-journald-audit.socket
● │ │ │ ├─systemd-journald-dev-log.socket
● │ │ │ ├─systemd-journald.socket
● │ │ │ ├─systemd-udevd-control.socket
● │ │ │ ├─systemd-udevd-kernel.socket
● │ │ │ ├─uuidd.socket
● │ │ │ ├─virtlockd.socket
● │ │ │ └─virtlogd.socket
● │ │ └─sysinit.target
● │ │   ├─apparmor.service
● │ │   ├─dev-hugepages.mount
● │ │   ├─dev-mqueue.mount
● │ │   ├─emergency.service
● │ │   ├─kmod-static-nodes.service
● │ │   ├─plymouth-read-write.service
● │ │   ├─proc-sys-fs-binfmt_misc.automount
● │ │   ├─sys-fs-fuse-connections.mount
● │ │   ├─sys-kernel-config.mount
● │ │   ├─sys-kernel-debug.mount
● │ │   ├─systemd-binfmt.service
● │ │   ├─systemd-hwdb-update.service
● │ │   ├─systemd-journald.service
● │ │   ├─systemd-machine-id-commit.service
● │ │   ├─systemd-modules-load.service
● │ │   ├─systemd-random-seed.service
● │ │   ├─systemd-sysctl.service
● │ │   ├─systemd-timesyncd.service
● │ │   ├─systemd-tmpfiles-setup-dev.service
● │ │   ├─systemd-tmpfiles-setup.service
● │ │   ├─systemd-udev-trigger.service
● │ │   ├─systemd-udevd.service
● │ │   ├─systemd-update-utmp.service
● │ │   ├─cryptsetup.target
● │ │   │ ├─systemd-ask-password-console.path
● │ │   │ └─systemd-ask-password-wall.path
● │ │   ├─emergency.target
● │ │   │ └─emergency.service
● │ │   ├─local-fs.target
● │ │   │ ├─-.mount
● │ │   │ ├─boot.mount
● │ │   │ ├─run-user-1000-gvfs.mount
● │ │   │ ├─run-user-1000.mount
● │ │   │ ├─systemd-fsck-root.service
● │ │   │ ├─systemd-quotacheck.service
● │ │   │ ├─systemd-remount-fs.service
● │ │   │ └─local-fs-pre.target
● │ │   │   ├─dm-event.service
● │ │   │   ├─friendly-recovery.service
● │ │   │   ├─keyboard-setup.service
● │ │   │   ├─lvm2-monitor.service
● │ │   │   ├─systemd-remount-fs.service
● │ │   │   └─systemd-tmpfiles-setup-dev.service
● │ │   └─swap.target
● │ │     ├─dev-disk-by\x2did-dm\x2dname\x2dubuntu\x2d\x2dvg\x2dswap_1.swap
● │ │     ├─dev-disk-by\x2did-dm\x2duuid\x2dLVM\x2dh6dVLlVqh0mPkldM2LvOKPvKxjYe…ap
● │ │     ├─dev-disk-by\x2duuid-8b4b6f36\x2d162f\x2d44bc\x2da5db\x2d6129540158f…ap
● │ │     ├─dev-dm\x2d1.swap
● │ │     ├─dev-mapper-ubuntu\x2d\x2dvg\x2dswap_1.swap
● │ │     └─dev-ubuntu\x2dvg-swap_1.swap
● │ ├─getty.target
● │ │ ├─getty-static.service
● │ │ ├─getty@tty1.service
● │ │ └─getty@tty7.service
● │ └─rescue.target
● │   ├─rescue.service
● │   └─sysinit.target
● │     ├─apparmor.service
● │     ├─dev-hugepages.mount
● │     ├─dev-mqueue.mount
● │     ├─emergency.service
● │     ├─kmod-static-nodes.service
● │     ├─plymouth-read-write.service
● │     ├─proc-sys-fs-binfmt_misc.automount
● │     ├─sys-fs-fuse-connections.mount
● │     ├─sys-kernel-config.mount
● │     ├─sys-kernel-debug.mount
● │     ├─systemd-binfmt.service
● │     ├─systemd-hwdb-update.service
● │     ├─systemd-journald.service
● │     ├─systemd-machine-id-commit.service
● │     ├─systemd-modules-load.service
● │     ├─systemd-random-seed.service
● │     ├─systemd-sysctl.service
● │     ├─systemd-timesyncd.service
● │     ├─systemd-tmpfiles-setup-dev.service
● │     ├─systemd-tmpfiles-setup.service
● │     ├─systemd-udev-trigger.service
● │     ├─systemd-udevd.service
● │     ├─systemd-update-utmp.service
● │     ├─cryptsetup.target
● │     │ ├─systemd-ask-password-console.path
● │     │ └─systemd-ask-password-wall.path
● │     ├─emergency.target
● │     │ └─emergency.service
● │     ├─local-fs.target
● │     │ ├─-.mount
● │     │ ├─boot.mount
● │     │ ├─run-user-1000-gvfs.mount
● │     │ ├─run-user-1000.mount
● │     │ ├─systemd-fsck-root.service
● │     │ ├─systemd-quotacheck.service
● │     │ ├─systemd-remount-fs.service
● │     │ └─local-fs-pre.target
● │     │   ├─dm-event.service
● │     │   ├─friendly-recovery.service
● │     │   ├─keyboard-setup.service
● │     │   ├─lvm2-monitor.service
● │     │   ├─systemd-remount-fs.service
● │     │   └─systemd-tmpfiles-setup-dev.service
● │     └─swap.target
● │       ├─dev-disk-by\x2did-dm\x2dname\x2dubuntu\x2d\x2dvg\x2dswap_1.swap
● │       ├─dev-disk-by\x2did-dm\x2duuid\x2dLVM\x2dh6dVLlVqh0mPkldM2LvOKPvKxjYe…ap
● │       ├─dev-disk-by\x2duuid-8b4b6f36\x2d162f\x2d44bc\x2da5db\x2d6129540158f…ap
● │       ├─dev-dm\x2d1.swap
● │       ├─dev-mapper-ubuntu\x2d\x2dvg\x2dswap_1.swap
● │       └─dev-ubuntu\x2dvg-swap_1.swap
● └─rescue.target
●   ├─rescue.service
●   └─sysinit.target
●     ├─apparmor.service
●     ├─dev-hugepages.mount
●     ├─dev-mqueue.mount
●     ├─emergency.service
●     ├─kmod-static-nodes.service
●     ├─plymouth-read-write.service
●     ├─proc-sys-fs-binfmt_misc.automount
●     ├─sys-fs-fuse-connections.mount
●     ├─sys-kernel-config.mount
●     ├─sys-kernel-debug.mount
●     ├─systemd-binfmt.service
●     ├─systemd-hwdb-update.service
●     ├─systemd-journald.service
●     ├─systemd-machine-id-commit.service
●     ├─systemd-modules-load.service
●     ├─systemd-random-seed.service
●     ├─systemd-sysctl.service
●     ├─systemd-timesyncd.service
●     ├─systemd-tmpfiles-setup-dev.service
●     ├─systemd-tmpfiles-setup.service
●     ├─systemd-udev-trigger.service
●     ├─systemd-udevd.service
●     ├─systemd-update-utmp.service
●     ├─cryptsetup.target
●     │ ├─systemd-ask-password-console.path
●     │ └─systemd-ask-password-wall.path
●     ├─emergency.target
●     │ └─emergency.service
●     ├─local-fs.target
●     │ ├─-.mount
●     │ ├─boot.mount
●     │ ├─run-user-1000-gvfs.mount
●     │ ├─run-user-1000.mount
●     │ ├─systemd-fsck-root.service
●     │ ├─systemd-quotacheck.service
●     │ ├─systemd-remount-fs.service
●     │ └─local-fs-pre.target
●     │   ├─dm-event.service
●     │   ├─friendly-recovery.service
●     │   ├─keyboard-setup.service
●     │   ├─lvm2-monitor.service
●     │   ├─systemd-remount-fs.service
●     │   └─systemd-tmpfiles-setup-dev.service
●     └─swap.target
●       ├─dev-disk-by\x2did-dm\x2dname\x2dubuntu\x2d\x2dvg\x2dswap_1.swap
●       ├─dev-disk-by\x2did-dm\x2duuid\x2dLVM\x2dh6dVLlVqh0mPkldM2LvOKPvKxjYevk…ap
●       ├─dev-disk-by\x2duuid-8b4b6f36\x2d162f\x2d44bc\x2da5db\x2d6129540158fd.…ap
●       ├─dev-dm\x2d1.swap
●       ├─dev-mapper-ubuntu\x2d\x2dvg\x2dswap_1.swap
●       └─dev-ubuntu\x2dvg-swap_1.swap

 

分析

参考にしたサイト
起動が遅い原因は?そんな時はsystemd-analyzeでチェック | Simple blog @atani
 

systemd-analyze
% systemd-analyze
Startup finished in 3.659s (kernel) + 41.036s (userspace) = 44.695s
graphical.target reached after 40.924s in userspace

 

systemd-analyze blame
% systemd-analyze blame 
         23.618s dev-sda1.device
         21.222s systemd-journal-flush.service
         18.372s dev-loop0.device
         18.366s dev-loop1.device
         14.284s systemd-udevd.service
         12.836s apparmor.service
         11.833s binfmt-support.service
         11.813s dns-clean.service
         10.058s proc-sys-fs-binfmt_misc.mount
          9.475s plymouth-quit-wait.service

 

systemd-analyze critical-chain

起動に時間が掛かったターゲットあるいはユニットを洗い出す。
下記を実行するにあたり、NIC を外しておいた。

% systemd-analyze critical-chain
The time after the unit is active or started is printed after the "@" character.
The time the unit takes to start is printed after the "+" character.

graphical.target @40.924s
└─multi-user.target @40.924s
  └─hddtemp.service @35.304s +7ms
    └─network-online.target @35.302s
      └─NetworkManager-wait-online.service @31.408s +3.893s
        └─NetworkManager.service @27.074s +4.333s
          └─dbus.service @26.581s
            └─basic.target @26.559s
              └─sockets.target @26.559s
                └─snapd.socket @26.535s +24ms
                  └─sysinit.target @26.534s
                    └─swap.target @26.534s
                      └─dev-disk-by\x2duuid-ea543863\x2d1459\x2d4246\x2daff9\x2d29fea0ebb9f6.swap @26.495s +39ms
                        └─dev-disk-by\x2duuid-ea543863\x2d1459\x2d4246\x2daff9\x2d29fea0ebb9f6.device @26.494s

 

systemd-analyze plot

結果を視覚化する。

% systemd-analyze plot > result.svg
% xdg-open result.svn

 
f:id:dnkrnka:20180929142900p:plain

*1:D-Bus (Desktop Bus) はメッセージバスと呼ばれる、アプリケーション間でやりとりを行うための、プロセス間通信(IPC)実装のひとつ

*2:/lib/systemd/systemd-fsck 辺りの情報は man コマンドで見ないと中々情報は無い