Open3

systemd

zulinx86zulinx86

systemd

  • systemd は、init システムの1つである。
  • init システムとは、Linux カーネルに最初に起動されるプロセスのことであり、システムが利用可能な状態になるための起動処理を行うプログラムのことであり、PID は 1 になる。
  • systemd は、SysV init (System V init または init とも) の後継の init システムという位置付けになっている。

Units

  • systemd は、unit (ユニット) という単位で、リソースやサービスを管理する。
  • unit のタイプには、以下のようなものがある。
  • unit は ini 形式のプレーンテキストファイルで記述される。
    • [Unit] セクション: unit のタイプに依存しない一般的な情報。
      • Description=: 人間用の unit の短いタイトル。
      • Documentation=: unit のドキュメントへの URI (複数ある場合は、スペース区切り) 。
      • Wants=: 他の unit への弱い依存関係。(詳細は次のコメント)
      • Requires=: 他の unit への強い依存関係。(詳細は次のコメント)
      • Upholds=
      • After=: どの unit よりも後に起動したいかを記述する。
      • Before=: どの unit よりも前に起動したいかを記述する。
    • [Install] セクション: unit のインストールに関する情報 (systemctl enable / systemctl disable コマンドの時に使用され、実行時には利用されない)
      • WantedBy=: systemctl enable 実行時に .wants/ ディレクトリ配下にシンボリックリンクが作成される。
      • RequiredBy=: systemctl enable 実行時に .requries/ ディレクトリ配下にシンボリックリンクが作成される。
      • UpheldBy=: systemctl enable 実行時に .upholds/ ディレクトリ配下にシンボリックリンクが作成される。
    • [Service] セクション
      • Type=: サービスの開始の完了をマネージャーに通知するメカニズム
        • simple: メインのサービスプロセスが fork() された直後 (新しいプロセスが execve() で対象のサービスバイナリを呼び出すよりも前) に、ユニットが開始されたと判断する。
        • exec: メインのサービスバイナリが実行された直後 (新しいプロセスが fork() されて、対象のサービスバイナリを execve() できた後) に、ユニットが開始されたと判断する。
        • forking: マネージャーによって fork() されたプロセスが終了した後 (exit() した後) に、ユニットが開始されたと判断する。マネージャーによって fork() されたプロセス (サービスの親プロセス) が、その後のメインサービスとなる子プロセスや必要なリソースをセットアップして終了する場合に用いる。
        • oneshot:
        • dbus
        • notify
        • notify-reload
        • idle
      • ExecStart=: サービス開始時に実行されるコマンド
      • ExecStartPre=:
      • ExecStartPost=:
  • 実行環境設定 ([Service], [Socket], [Mount] または [Swap])
    • Environment=: 実行されるプロセスの環境変数を設定する。
    • EnvironmentFile=: 実行されるプロセスの環境変数をファイルから読み込み設定する。

systemctl

  • systemd を管理するための CLI ツール
  • unit ファイルコマンド
    • systemctl list-unit-files [PATTERN...]: システムにインストールされている unit ファイルをリストする

参考リンク

zulinx86zulinx86

依存関係 (requirement dependencies) と順序関係 (ordering dependencies)

  • 依存関係と順序関係は、直交 (orthogonal) している。
    • 例: foo.service が正常に動作するために bar.service が必要であっても、bar.servicefoo.service より先に起動してないといけないとは限らない。順序関係が必要なければ、これらを並行で起動させることができ、システムの起動時間の短縮に繋がる場合がある。

依存関係 (requirement dependency) の記述の仕方

Wants= / WantedBy=

  • 弱い依存関係を設定するために使用する。
  • 対象のユニットが起動される場合は、Wants= にリストされたユニットも起動される。
  • Wants= にリストされたユニットが正常に起動できたかどうかに関わらず、対象のユニットは起動される。
  • WantedBy= は、Wants= の逆を意味していて、リストされているユニットから依存されていることを意味する。

Requires= / RequiredBy=

  • Wants= より強い依存関係を設定するために使用する。
  • 対象のユニットが起動される場合は、Requires= にリストされたユニットも起動される。
  • Requires= にリストされたユニットが正常に起動できず、その起動に失敗したユニットが After= にも含まれていた場合は、対象のユニットは起動されない。
  • After= に含まれているがどうかに関わらず、Requires= にリストされたユニットが停止 or 再起動された場合には、対象のユニットも停止 or 再起動される。
  • RequiredBy= は、Requires= の逆を意味していて、リストされているユニットから依存されていることを意味する。

順序関係 (ordering dependency) の記述の仕方

Before=

  • Before= にリストされたユニットよりも先に、対象のユニットが起動されなければならない。

After=

  • After= にリストされたユニットよりも後に、対象のユニットが起動されなければならない。

確認方法

依存関係の確認方法

指定したユニットが依存しているユニットをリストする。

$ sudo systemctl list-dependencies [<unit>...]

指定したユニットに依存しているユニットをリストする。

$ sudo systemctl list-dependencies --reverse [<unit>...]

順序関係の確認方法

指定したユニットよりも後に起動すべきユニットをリストする。

$ sudo systemctl list-dependencies --before [<unit>...]

指定したユニットよりも前に起動しているべきユニットをリストする。

$ sudo systemctl list-dependencies --after [<unit>...]
zulinx86zulinx86

Hands-On

Amazon Linux 2023 AMI で色々実際に確認していく。

ちゃんと systemd は PID 1 で起動してる。

$ ps x -q 1
    PID TTY      STAT   TIME COMMAND
      1 ?        Ss     0:03 /usr/lib/systemd/systemd --switched-root --system --deserialize=32

kernel のコマンドラインには init= は指定されていないので、/sbin/init が呼び出されているはず。

$ cat /proc/cmdline
BOOT_IMAGE=(hd0,gpt1)/boot/vmlinuz-6.1.75-99.163.amzn2023.x86_64 root=UUID=f2901285-17a4-4f0e-b17b-213de684d2c7 ro console=tty0 console=ttyS0,115200n8 nvme_core.io_timeout=4294967295 rd.emergency=poweroff rd.shell=0 selinux=1 security=selinux quiet

/sbin/init は、systemd へのシンボリックリンクになっている。

$ ls -l /sbin/init
lrwxrwxrwx. 1 root root 22 Jan 17 22:52 /sbin/init -> ../lib/systemd/systemd

しかし、/lib/systemd/systemd/usr/lib/systemd/systemd へのシンボリックリンクになっているわけではない。ただし、/lib/usr/lib へのシンボリックリンクになっているので、/lib/systemd/systemd/usr/lib/systemd/systemd は同じファイルである。

$ ls -l /lib/systemd/systemd
-rwxr-xr-x. 1 root root 102904 Jan 17 22:52 /lib/systemd/systemd

$ ls -l /lib
lrwxrwxrwx. 1 root root 7 Jan 30  2023 /lib -> usr/lib
$ realpath /sbin/init
/usr/lib/systemd/systemd

デフォルトのターゲットは graphical.target になっており、default.target はちゃんと graphical.target へのシンボリックリンクになっている。

$ systemctl get-default
graphical.target

$ ls -l /usr/lib/systemd/system/default.target
lrwxrwxrwx. 1 root root 16 Jan 17 22:52 /usr/lib/systemd/system/default.target -> graphical.target

graphical.target の中身は以下の通り。

$ systemctl cat graphical.target
# /usr/lib/systemd/system/graphical.target
#  SPDX-License-Identifier: LGPL-2.1-or-later
#
#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

[Unit]
Description=Graphical Interface
Documentation=man:systemd.special(7)
Requires=multi-user.target
Wants=display-manager.service
Conflicts=rescue.service rescue.target
After=multi-user.target rescue.service rescue.target display-manager.service
AllowIsolate=yes

システムには 316 個の unit ファイルが入ってた。

$ systemctl list-unit-files
UNIT FILE                              STATE           PRESET
boot-efi.automount                     generated       -
# snipped
update-motd.timer                      enabled         enabled

316 unit files listed.