hiroの長い冒険日記

主にコンピュータ周辺の興味を持った内容を綴ります

systemd ... SysVinit との違いと動作について その4

前回は、systemd の automount、mount unit について、kernel の機能を含めて調べてみた。

hiro20180901.hatenablog.com

今回は、service unit について調べてみた。

service unit

service unit は、SysVinit の /etc/rc.d の init file に相当する unit で、各種 daemon を起動したり、起動直後や終了前に処理を行ったりする。
service unit は数が多い(現在の環境で130)ので、先頭文字が a 〜 k までの 41 units について調べてみた。以下、特記なき場合は .service を省略する。

[a-k]*service

equj65.net
前にも紹介したリンク先だが、man systemctl の STATE 欄の日本語訳が記載されているので引用する。

  • enabled 有効化されている。UnitファイルのWantedBy句に指定されたtargetと同時に起動する。
  • disabled 無効化されている。UnitファイルのWantedBy句に指定されたtargetと同時起動しない。
  • masked マスクされている。自動起動対象とならないし、手動起動もできない。
  • linked リンクされている。Unitファイルは異なるUnitファイルへのシンボリックリンクとなっている。(Systemdはリンク先の別Unitファイルの設定を読み取る)
  • static 有効化/無効化の対象外。UnitファイルにWantedBy句がそもそも指定されていない。

$ systemctl list-unit-files [a-k]*service
UNIT FILE                              STATE   
apt-daily-upgrade.service              static  
apt-daily.service                      static  
autovt@.service                        enabled 
binfmt-support.service                 enabled 
bootlogd.service                       masked  
bootlogs.service                       masked  
bootmisc.service                       masked  
checkfs.service                        masked  
checkroot-bootclean.service            masked  
checkroot.service                      masked  
console-getty.service                  disabled
console-setup.service                  enabled 
container-getty@.service               static  
cron.service                           enabled 
cryptdisks-early.service               masked  
cryptdisks.service                     masked  
dbus-org.freedesktop.hostname1.service static  
dbus-org.freedesktop.locale1.service   static  
dbus-org.freedesktop.login1.service    static  
dbus-org.freedesktop.network1.service  enabled 
dbus-org.freedesktop.resolve1.service  disabled
dbus-org.freedesktop.timedate1.service static  
dbus.service                           static  
debug-shell.service                    disabled
display-manager.service                enabled 
emergency.service                      static  
fuse.service                           masked  
getty-static.service                   static  
getty@.service                         enabled 
halt.service                           masked  
hostname.service                       masked  
hwclock.service                        masked  
ifup@.service                          static  
initrd-cleanup.service                 static  
initrd-parse-etc.service               static  
initrd-switch-root.service             static  
initrd-udevadm-cleanup-db.service      static  
keyboard-setup.service                 enabled 
killprocs.service                      masked  
kmod-static-nodes.service              static  
kmod.service                           static  

41 unit files listed.

apt-daily-upgrade、apt-daily

debian/ubuntu 特有の unit で、apt update と apt upgrade を自動で実行する。同名の timer unit もある。
apt-daily.service:

[Unit]
Description=Daily apt download activities
Documentation=man:apt(8)
ConditionACPower=true
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/lib/apt/apt.systemd.daily update

apt-daily.timer:

[Unit]
Description=Daily apt download activities

[Timer]
OnCalendar=*-*-* 6,18:00
RandomizedDelaySec=12h
Persistent=true

[Install]
WantedBy=timers.target

man systemd.timer:

For each timer file, a matching unit file must exist, describing the unit to activate when the timer elapses. By default, a service by the same name as the timer (except for the suffix) is activated. Example: a timer file foo.timer activates a matching service foo.service. The unit to activate may be controlled by Unit= (see below).

timer unit が起動された際に同名の service が起動される。実体は /usr/lib/apt/apt.systemd.daily である。

autovt@、getty@、container-getty@、console-getty、、getty-static

これらは、terminal に関係する unit である。SysVinit 時代は /etc/inittab に getty が複数並んでいて常に複数が起動していたが、systemd では動的に必要な分だけが起動するようになっている。

$ systemctl list-unit-files *tty*service auto*service
UNIT FILE                STATE   
autovt@.service          enabled 
console-getty.service    disabled
container-getty@.service static  
getty-static.service     static  
getty@.service           enabled 
serial-getty@.service    disabled

6 unit files listed.

$ pwd
/lib/systemd/system
$ ls -l *tty* autovt*
lrwxrwxrwx 1 root root   14 Feb 17 17:22 autovt@.service -> getty@.service
-rw-r--r-- 1 root root  770 Feb 17 17:22 console-getty.service
-rw-r--r-- 1 root root  791 Feb 17 17:22 container-getty@.service
-rw-r--r-- 1 root root  342 Feb 17 17:22 getty-static.service
-rw-r--r-- 1 root root  460 Feb 17 17:22 getty.target
-rw-r--r-- 1 root root 1737 Feb 17 17:22 getty@.service
-rw-r--r-- 1 root root 1038 Feb 17 17:22 serial-getty@.service

getty.target.wants:
total 0
lrwxrwxrwx 1 root root 23 Feb 17 17:22 getty-static.service -> ../getty-static.service

enable になっているのは、autovt@ と getty@ の2つ。autovt@ は getty@ の symbolic link なので、結局は getty@ のみ有効。それ以外の service の機能は次の通り:

  • console-getty は /dev/console を端末に接続する為の unit
  • container-getty はコンテナ(systemd-nspawn)用の仮想端末を接続する為の unit

techracho.bpsinc.jp

  • getty-static は dbus と logind が使えない時に tty[2-6] の仮想端末を使えるようにする unit
  • serial-getty は実際の serial line 用の unit

$ find ./ -name "getty.target"
./multi-user.target.wants/getty.target
./getty.target

$ find /etc/systemd | grep tty
/etc/systemd/system/getty.target.wants
/etc/systemd/system/getty.target.wants/getty@tty1.service

$ ls -l /etc/systemd/system/getty.target.wants/getty@tty1.service 
lrwxrwxrwx 1 root root 34 Jan 20 22:06 /etc/systemd/system/getty.target.wants/getty@tty1.service -> /lib/systemd/system/getty@.service

  • getty@.service の起動元となっているのは getty.target である。getty.target が multi-user.target.want に含まれている事から、graphical.target や multi-user.target で起動している場合には getty.target が有効となっている。
  • '@' が末尾に付いている unit は template unit という(man systemd.unit)。上の例では、/etc 以下にある getty@tty1.service は getty@.service の symbolic link となっているが、起動時の最初の仮想端末用の getty を確実に起動させる為だと思われる。getty@.service の中で、'@' 以降の 'tty1' が %I で参照されていて、agetty に渡されて仮想端末が起動している。Ctrl + Alt + F[2-6] で仮想端末に login すると、unit file は無いが該当の tty[2-6] の service が有効になる。何をきっかけとして動的に起動するのだろうか ... 後で調べる。

$ systemctl list-units getty*service
UNIT               LOAD   ACTIVE SUB     DESCRIPTION                                                                                                        
getty@tty1.service loaded active running Getty on tty1                                                                                                      
getty@tty2.service loaded active running Getty on tty2                                                                                                      
getty@tty3.service loaded active running Getty on tty3                                                                                                      
getty@tty6.service loaded active running Getty on tty6                                                                                                      

LOAD   = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB    = The low-level unit activation state, values depend on unit type.

4 loaded units listed. Pass --all to see loaded but inactive units, too.
To show all installed unit files use 'systemctl list-unit-files'.

  • autovt@ は getty@ の symbolic link になっている。ArchWiki によると autovt@ への symbolic link を変更すると、getty の代わりに別の virtual terminal を使用できる模様。KMSCON は cjk を扱える virtual terminal。

wiki.archlinux.jp

  • autovt@ は停止しない方が良い。仮想端末の1番目が使用できなくなる。

https://hanipo.net/node/100hanipo.net

端末については、まだまだ知らない事が多いので、別の機会にちゃんと調べたいと考えている。Wikipedia へのリンク:
仮想コンソール (Wikibedia)

binfmt-support

前回の mount unit にも存在していた binfmt の support 用の unit。mount 側は virtual filesystem を mount しているが、こちらは update-binfmts を oneshot で実行している。

bootlogd、bootlogs、bootmisc

全て masked されていて、/dev/null への symbolic link である。

$ ls -l *bootlogd* *bootlogs* *bootmisc*
lrwxrwxrwx 1 root root 9 Feb 17 17:22 bootlogd.service -> /dev/null
lrwxrwxrwx 1 root root 9 Feb 17 17:22 bootlogs.service -> /dev/null
lrwxrwxrwx 1 root root 9 Feb 17 17:22 bootmisc.service -> /dev/null
lrwxrwxrwx 1 root root 9 Feb 17 17:22 stop-bootlogd-single.service -> /dev/null
lrwxrwxrwx 1 root root 9 Feb 17 17:22 stop-bootlogd.service -> /dev/null

man systemd.unit:

If a unit file is empty (i.e. has the file size 0) or is symlinked to /dev/null, its configuration will not be loaded and it appears with a load state of "masked", and cannot be activated. Use this as an effective way to fully disable a unit, making it impossible to start it even manually.

/dev/null に link されている unit は常に無効、mask されている。

  • bootlogd は SysVinit 時代の boot log を記録する dameon なので、systemd では不要。
  • bootlogs、bootmisc はググってもよく分からないが、bootlogd と同様に SysVinit 時代の名残かと思う。

checkfs、checkroot-bootclean、checkroot

全て masked されている。

$ ls -l *checkfs* *checkroot*
lrwxrwxrwx 1 root root 9 Feb 17 17:22 checkfs.service -> /dev/null
lrwxrwxrwx 1 root root 9 Feb 17 17:22 checkroot-bootclean.service -> /dev/null
lrwxrwxrwx 1 root root 9 Feb 17 17:22 checkroot.service -> /dev/null

bootlogd 等と同様の状態。

  • checkfs は SysVinit の時に、起動時に fsck を実行する daemon だった。容量が大きくなって、毎回 fsck するのは難しくなって、やらなくなったような記憶がある。
  • checkroot も checkfs と同様かと思う。

console-setup

  • multi-user.target から WantedBy されていて、console の font と keymap を設定する。実体は /lib/console-setup/console-setup.sh。
  • setupcon、/etc/default/console-setup、/etc/default/keyboard 辺りで詳細が分かる。

cron

  • multi-user.target から WantedBy されていて、cron daemon を起動する。
  • systemd の timer unit はあるが、昔ながらの cron daemon も有効になっている。
  • apt や logrotate、man-db 等が起動されるようになっている。

cryptdisks-early、cryptdisks

  • 共に /dev/null への link であり無効。volume の暗号化に関する service だと思われる。
  • systemd-cryptsetup を含め、volume の暗号化をする場合には詳しく調べてみる。

dbus*

先頭に dbus の付いた unit が6つ。

  • dbus*.network1.service が enabled
  • dbus*.resolve1.service が disabled
  • 他5つは static

multi-user.target の wantsdbus.service、sockets.target の wantsdbus.socket が入っている。おそらく、systemd.networkd で network の設定をしているので、dbus*.network1 が有効になっているのだろう。

dbus については知らないことが多いので、別途詳細を調べる。

debug-shell

一般的なトラブルシューティング - 2.2 リカバリシェル - ArchWiki

また、カーネルパラメータに systemd.debug-shell を追加するか、あるいは debug-shell.service を有効化することで tty9 に root シェルを追加することもできます (Ctrl+Alt+F9 でアクセス可能)。root シェルが開きっぱなしになっているとセキュリティ上危険なので、修復が終わったらサービスは無効化してください。

なので、disable になっている。引用した部分の前にある grub の kernel 起動条件の変更も、幸いにして使った事は無いが、非常時には役立つと思う。

display-manager

display-manager は、現在の Desktop 環境の symbolic link である。今の環境では lightdm.service への link になっている。

$ ls -l /etc/systemd/system/display-manager.service 
lrwxrwxrwx 1 root root 35 Feb 11 22:05 /etc/systemd/system/display-manager.service -> /lib/systemd/system/lightdm.service

lightdm については次の機会に調べてみる。

emergency

同名の target unit も存在している。通常は disabled になっているが、enable はできない。systemctl emergency で移行する...が、debug-shell に記載した ArchWiki では、

  • rescue は rootfs を rw で mount した後
  • emergency は rootfs を mount する前

に single user mode になると書かれているが、qemu (kvm) 仮想マシンで試すと、emergency でも rootfs を rw で mount していた。emergency.service 内にも umount 等の記載は無い。rescue 等、systemctl の system commands の内容は別の機会に調べてみる。

fuse (Filesystem in Userspace、FUSE)

mount unit は enable になっていたが、service は masked、/dev/null に link されている。

halt

同名の target unit も存在している。halt.service は masked、/dev/null に link されている。動作については emergency 等と一緒に後で調べてみる。

hostname

hostname.service は /dev/null の link。実際に使用される unit は systemd-hostnamed.service の模様。

$ systemctl list-units *hostname*
0 loaded units listed. Pass --all to see loaded but inactive units, too.
To show all installed unit files use 'systemctl list-unit-files'.

$ hostnamectl | grep hostname
   Static hostname: debian

$ systemctl list-units *hostname*
UNIT                      LOAD   ACTIVE SUB     DESCRIPTION                     
systemd-hostnamed.service loaded active running Hostname Service                

LOAD   = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB    = The low-level unit activation state, values depend on unit type.

1 loaded units listed. Pass --all to see loaded but inactive units, too.
To show all installed unit files use 'systemctl list-unit-files'.

hostnamectl を実行すると、一時的に systemd-hostnamed.service が有効となり、時間が経過するとまた無効になる。この辺りがどういう仕組みで動作しているのか、後で詳しく調べてみる。

hwclock

hwclock.service は /dev/null の link。hwclock 自体は PC本体と linux の clock を同期させる為の command。
qiita.com
unit を作成して同期させる方法もある模様。

ifup@

debian の /etc/network/interfaces を読み込んで設定する為の service だろう。template unit になっているので、interface 名が後に付いた形で unit として読み込まれると思う。

initrd*

alpha.mixi.co.jp
static になっているが、起動時に使用する unit と思われる。

keyboard-setup

console の keyboard layout を 設定する unit で、起動時に oneshot で実行されているので、起動後には static になっている。実体は /lib/console-setup/keyboard-setup.sh。

killprocs

/dev/null に link されていて、masked になっている。詳細は分からず。/lib/lsb/init-functions で定義されている killproc と関係ある?

kmod-static-nodes

sysinit.service の前に one shot で起動し、kernel module で /dev 以下に (udev の管理外で) 静的に作成される device の情報を記録する unit である。kmod static-nodes コマンドの実行結果を特定の file に書き込んでいて、device の作成は別に行なっている模様。

kmod

起動時に kernel module を読み込む為の unit らしい。

結果

  • systemd service の先頭文字が a 〜 k の unit について、機能を調べてみた。
  • /dev/null に symbolic link されている unit が思いの外に多く、存在する理由が分からない。何かしらの理由があって存在しているのだろうが、最後まで調べたら分かるのかもしれない。
  • SysVinit の init script と同じように動作するものと、起動時に one shot で動作するもの、emergency.service の様に target と同じように機能するものが混在しているので、ちょっと分かり難い。
  • timer と同名の service はひとまとまりなので兎も角、target と同名の service が存在するのは戸惑いがある。target には機能を持たせる事が出来ないからなのだろうが、service だけでも良さそうな気がする。これも、最後まで調べたら分かるだろう。
  • dbus や udev、kernel の機能と深く連携しているので、systemd だけを調べても理解が進まない事がだんだん分かってきた。平行して dbus や udev を調べてみる。