この連載では、Fedora 17での実装をベースとして、systemdの考え方や仕組み、利用方法を説明します。今後出てくる予定のRHEL7での実装とは異なる部分があるかも知れませんが、その点はご了承ください。
今回は、表題の小ネタを2つお届けします。
cgroups
systemdの管理下では、すべてのプロセスについて、cgroupsによる分類が行われます。cgroupsでは、グループに階層構造を持たせることができますが、systemdは「systemグループ」と「userグループ」を用意した上で、その下にサブグループを作成していきます。
グループ | 説明 |
---|---|
system | systemdから起動するserviceについて、この下に該当service用のサブグループを作成します。 |
user | この下にユーザアカウントごとのサブグループを作成します。その下には、さらに、ログイン端末ごとのサブグループを作成します。 |
各プロセスのグループは次のコマンドで確認できます。実行コマンド名の前の数値は、該当プロセスのPIDです。
# systemd-cgls ├ user │ ├ enakai │ │ ├ 10 │ │ │ ├ 1317 sshd: enakai [priv] │ │ │ ├ 1321 sshd: enakai@pts/2 │ │ │ └ 1322 -bash │ │ └ 9 │ │ ├ 1291 sshd: enakai [priv] │ │ ├ 1295 sshd: enakai@pts/1 │ │ └ 1296 -bash │ └ root │ ├ 11 │ │ ├ 435 login -- root │ │ └ 1347 -bash │ └ 1 │ ├ 549 sshd: root@pts/0 │ ├ 553 -bash │ ├ 1363 systemd-cgls │ └ 1364 cat └ system ├ 1 /usr/lib/systemd/systemd ├ chronyd.service │ └ 713 /usr/sbin/chronyd -u chrony ├ sm-client.service │ └ 542 sendmail: Queue runner@01:00:00 for /var/spool/clientmqueue ├ sendmail.service │ └ 522 sendmail: accepting connections ├ sshd.service │ └ 725 /usr/sbin/sshd -D ├ crond.service │ └ 437 /usr/sbin/crond -n ├ dbus.service │ ├ 431 /bin/dbus-daemon --system --address=systemd: --nofork --systemd-... │ ├ 452 /usr/libexec/polkit-1/polkitd --no-debug │ └ 469 /usr/sbin/modem-manager ├ systemd-logind.service │ └ 412 /usr/lib/systemd/systemd-logind ├ NetworkManager.service │ ├ 410 /usr/sbin/NetworkManager --no-daemon │ └ 485 /sbin/dhclient -d -4 -sf /usr/libexec/nm-dhcp-client.action -pf ... ├ rsyslog.service │ └ 409 /sbin/rsyslogd -n -c 5 ├ auditd.service │ └ 407 /sbin/auditd -n ├ udev.service │ ├ 288 /usr/lib/udev/udevd │ ├ 348 /usr/lib/udev/udevd │ └ 349 /usr/lib/udev/udevd └ systemd-journald.service └ 279 /usr/lib/systemd/systemd-journald
これにより、systemdは、serviceごとにcgroupsによるリソースの割り当てを細かに制御することができるようになります。システム管理者は、cgroupsの設定を直接に行うのではなく、serviceの設定ファイルにリソースの割り当て条件を記載することで、systemdが該当serviceのグループに対して必要な設定を行う形になります。現在、systemdとのインテグレーションに合わせて、cgroupsの大幅な改変が予定されていますので、具体的な設定方法はこれから整備されていくと思われます。
参考資料
・[HEADSUP] cgroup changes:2013/06/21にLennartがcgoupsの改変について投稿したメール
一方、serviceごとにプロセスをグループ化することには、cgroupsの設定以外にも恩恵があります。KILLシグナルでserviceを強制停止する場合、同じグループに属するプロセスすべてを強制停止することで、該当のserviceを完全に停止することができます。デーモンプロセスでは、「double fork」という手法でプロセスの親子関係を分断することがあるため、プロセスの親子関係だけで関連するプロセスを網羅できない点に注意してください。上記のコマンド出力からわかるように、systemdは、それぞれのグループ内のプロセスのPIDをすべて把握しています。これまでは、PIDファイルで停止するプロセスを特定する必要がありましたが、この必要もなくなります。
具体的には、systemctlコマンドのkillオプションを使用すると、指定のserviceに属するすべてのプロセスにまとめてシグナルが送信されます。シグナル名(シグナル番号)は-sオプションで指定します。
# systemctl kill -s9 sshd.service
service内で最初に起動したmainプロセスだけにシグナルを送りたい場合は、「--kill-who=main」オプションを指定します。
# systemctl kill -sSIGHUP --kill-who=main sshd.service
参考資料
・systemd for Administrators, Part IV - Killing Services
また、systemctlコマンド(stopオプション)でserviceを停止する場合にもこの仕組みが利用されます。具体的には、次の順序で停止処理が行われます。
・「ExecStop=」オプションで指定したコマンドを実行
・グループ内の全てのプロセスにSIGTERMを送信(*)
・グループ内の全てのプロセスにSIGKILLを送信(*)
(*)「KillMode=process」を指定した場合は、最初に起動したプロセスのみに送信
動的生成Unit
参考資料
・systemd-specialのmanページ
systemdが管理するUnitは、/usr/lib/systemd/system/以下、もしくは/etc/systemd/system/以下の設定ファイルで定義されますが、この他にもsystemdが動的に生成するUnitがあります。たとえば、ファイルシステムのマウント処理を行うmountタイプのUnitがありますが、systemdは、/etc/fstabのエントリーを参照して、対応するmountタイプのUnitを生成します。(設定ファイルを生成するわけではありません。対応する設定ファイルがない状態で、Unitの存在だけが認識される形になります。)Unitの名称は、「<マウントポイントのパスで「/」を「-」置換したもの>.mount」となります。
次の例では、-.mount(ルートファイルシステム)とboot.mount(/bootファイルシステム)が、/etc/fstabから動的に生成されたUnitになります。
# systemctl list-units --type=mount UNIT LOAD ACTIVE SUB JOB DESCRIPTION -.mount loaded active mounted / boot.mount loaded active mounted /boot dev-hugepages.mount loaded active mounted Huge Pages File System dev-mqueue.mount loaded active mounted POSIX Message Queue File System media.mount loaded active mounted Media Directory sys-kernel-config.mount loaded active mounted Configuration File System sys-kernel-debug.mount loaded active mounted Debug File System
これらのUnitは、「local-fs.target」の前提Unitとして自動設定されます。
# systemctl show local-fs.target | grep Requires Requires=boot.mount -.mount
この他には、デバイスを表すdeviceタイプのUnitも動的に生成されます。これは、udevが新しいデバイスを認識したタイミングで、「systemd」というudevタグを付けると、それを受け取ったsystemdが対応するUnitを生成して有効化します。(Fedora 17のudevでは、デフォルトで前述のudevタグを付けるように設定されています。)Unitの名称は、「<該当デバイスの/sysファイルシステムパス(「/」を「-」に置換)>.device」になります。
次の例では、「sys-devices-」で始まるUnitがこれに該当します。(--fullオプションは長いUnit名を省略せずに表示するオプションです。)
# systemctl list-units --type=device --full UNIT LOAD ACTIVE SUB JOB DESCRIPTION sys-devices-pci0000:00-0000:00:01.1-ata2-host1-target1:0:0-1:0:0:0-block-sr0.device loaded active plugged QEMU_DVD-ROM sys-devices-pci0000:00-0000:00:03.0-virtio0-net-eth0.device loaded active plugged Virtio network device sys-devices-pci0000:00-0000:00:04.0-sound-card0.device loaded active plugged 82801FB/FBM/FR/FW/FRW (ICH6 Family) High Definition Audio Controller sys-devices-pci0000:00-0000:00:05.0-virtio1-virtio\x2dports-vport1p1.device loaded active plugged /sys/devices/pci0000:00/0000:00:05.0/virtio1/virtio-ports/vport1p1 sys-devices-pci0000:00-0000:00:06.0-virtio2-block-vda-vda1.device loaded active plugged /sys/devices/pci0000:00/0000:00:06.0/virtio2/block/vda/vda1 sys-devices-pci0000:00-0000:00:06.0-virtio2-block-vda-vda2.device loaded active plugged /sys/devices/pci0000:00/0000:00:06.0/virtio2/block/vda/vda2 sys-devices-pci0000:00-0000:00:06.0-virtio2-block-vda.device loaded active plugged /sys/devices/pci0000:00/0000:00:06.0/virtio2/block/vda sys-devices-platform-serial8250-tty-ttyS1.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS1 sys-devices-platform-serial8250-tty-ttyS2.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS2 sys-devices-platform-serial8250-tty-ttyS3.device loaded active plugged /sys/devices/platform/serial8250/tty/ttyS3 sys-devices-pnp0-00:04-tty-ttyS0.device loaded active plugged /sys/devices/pnp0/00:04/tty/ttyS0 sys-devices-virtual-block-dm\x2d0.device loaded active plugged /sys/devices/virtual/block/dm-0 sys-devices-virtual-block-dm\x2d1.device loaded active plugged /sys/devices/virtual/block/dm-1 sys-devices-virtual-tty-tty0.device loaded active plugged /sys/devices/virtual/tty/tty0 sys-devices-virtual-tty-tty1.device loaded active plugged /sys/devices/virtual/tty/tty1 sys-devices-virtual-tty-tty10.device loaded active plugged /sys/devices/virtual/tty/tty10 sys-devices-virtual-tty-tty11.device loaded active plugged /sys/devices/virtual/tty/tty11 sys-devices-virtual-tty-tty12.device loaded active plugged /sys/devices/virtual/tty/tty12 sys-devices-virtual-tty-tty2.device loaded active plugged /sys/devices/virtual/tty/tty2 sys-devices-virtual-tty-tty3.device loaded active plugged /sys/devices/virtual/tty/tty3 sys-devices-virtual-tty-tty4.device loaded active plugged /sys/devices/virtual/tty/tty4 sys-devices-virtual-tty-tty5.device loaded active plugged /sys/devices/virtual/tty/tty5 sys-devices-virtual-tty-tty6.device loaded active plugged /sys/devices/virtual/tty/tty6 sys-devices-virtual-tty-tty7.device loaded active plugged /sys/devices/virtual/tty/tty7 sys-devices-virtual-tty-tty8.device loaded active plugged /sys/devices/virtual/tty/tty8 sys-devices-virtual-tty-tty9.device loaded active plugged /sys/devices/virtual/tty/tty9 sys-module-configfs.device loaded active plugged /sys/module/configfs sys-subsystem-net-devices-eth0.device loaded active plugged Virtio network device
特に、Bluetoothコントローラ、プリンタ、スマートカード、サウンドカードについては、それぞれ、bluetooth.target, printer.target, smartcard.target, sound.targetが自動的に前提Unitに指定されます。つまり、たとえば、サウンドカードが挿入されると、そのタイミングでsound.targetが有効化されます。そこで、サウンドカードを必要とするUnitをsound.targetの前提Unitとしておけば、サウンドカードが挿入されたタイミングでこれらのUnitが有効化されることになります。