4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

少し前ではありますが、isucon13に出ました。
初めてだったので、わからないことだらけでした。
今回は、そのうちの一つであるsystemdについてまとめます。

環境

こちらのisucon13で、Ruby実装を使って検証しています。

systemdとは

systemd is a system and service manager for Linux operating systems. When run as first process on boot (as PID 1), it acts as init system that brings up and maintains userspace services.

Linuxにおけるシステム管理やサービス管理の仕組みです。
PIDが1のプロセスとして起動するinitシステムであり、プロセス階層の根元になります。

プロセスツリーの例(isucon13 Ruby実装)
$ pstree -p
systemd(1)─┬─acpid(369)
           ├─agetty(410)
           ├─agetty(421)
           ├─amazon-ssm-agen(392)─┬─{amazon-ssm-agen}(610)
           │                      ├─{amazon-ssm-agen}(611)
           │                      ├─{amazon-ssm-agen}(612)
           │                      ├─{amazon-ssm-agen}(613)
           │                      ├─{amazon-ssm-agen}(653)
           │                      ├─{amazon-ssm-agen}(956)
           │                      └─{amazon-ssm-agen}(1898)
           ├─bundle(2793)─┬─bundle(2794)─┬─{bundle}(2800)
           │              │              ├─{bundle}(2840)
           │              │              ├─{bundle}(2841)
           │              │              ├─{bundle}(2842)
           │              │              ├─{bundle}(2843)
           │              │              └─{bundle}(2844)
           │              ├─bundle(2795)─┬─{bundle}(2801)
           │              │              ├─{bundle}(2810)
           │              │              ├─{bundle}(2811)
           │              │              ├─{bundle}(2812)
           │              │              ├─{bundle}(2813)
           │              │              └─{bundle}(2814)
           │              ├─bundle(2796)─┬─{bundle}(2802)
           │              │              ├─{bundle}(2835)
           │              │              ├─{bundle}(2836)
           │              │              ├─{bundle}(2837)
           │              │              ├─{bundle}(2838)
           │              │              └─{bundle}(2839)
           │              ├─bundle(2797)─┬─{bundle}(2804)
           │              │              ├─{bundle}(2825)
           │              │              ├─{bundle}(2826)
           │              │              ├─{bundle}(2827)
           │              │              ├─{bundle}(2828)
           │              │              └─{bundle}(2829)
           │              ├─bundle(2798)─┬─{bundle}(2803)
           │              │              ├─{bundle}(2815)
           │              │              ├─{bundle}(2816)
           │              │              ├─{bundle}(2817)
           │              │              ├─{bundle}(2818)
           │              │              └─{bundle}(2819)
           │              ├─bundle(2799)─┬─{bundle}(2807)
           │              │              ├─{bundle}(2830)
           │              │              ├─{bundle}(2831)
           │              │              ├─{bundle}(2832)
           │              │              ├─{bundle}(2833)
           │              │              └─{bundle}(2834)
           │              ├─bundle(2805)─┬─{bundle}(2808)
           │              │              ├─{bundle}(2845)
           │              │              ├─{bundle}(2846)
           │              │              ├─{bundle}(2847)
           │              │              ├─{bundle}(2848)
           │              │              └─{bundle}(2849)
           │              └─bundle(2806)─┬─{bundle}(2809)
           │                             ├─{bundle}(2820)
           │                             ├─{bundle}(2821)
           │                             ├─{bundle}(2822)
           │                             ├─{bundle}(2823)
           │                             └─{bundle}(2824)
           ├─chronyd(414)───chronyd(424)
           ├─cron(373)
           ├─dbus-daemon(374)
           ├─multipathd(152)─┬─{multipathd}(167)
           │                 ├─{multipathd}(169)
           │                 ├─{multipathd}(170)
           │                 ├─{multipathd}(171)
           │                 ├─{multipathd}(172)
           │                 └─{multipathd}(173)
           ├─mysqld(709)─┬─{mysqld}(721)
           │             ├─{mysqld}(722)
           │             ├─{mysqld}(723)
           │             ├─{mysqld}(724)
           │             ├─{mysqld}(725)
           │             ├─{mysqld}(726)
           │             ├─{mysqld}(727)
           │             ├─{mysqld}(728)
           │             ├─{mysqld}(729)
           │             ├─{mysqld}(732)
           │             ├─{mysqld}(740)
           │             ├─{mysqld}(741)
           │             ├─{mysqld}(742)
           │             ├─{mysqld}(743)
           │             ├─{mysqld}(744)
           │             ├─{mysqld}(745)
           │             ├─{mysqld}(748)
           │             ├─{mysqld}(749)
           │             ├─{mysqld}(750)
           │             ├─{mysqld}(751)
           │             ├─{mysqld}(752)
           │             ├─{mysqld}(753)
           │             ├─{mysqld}(754)
           │             ├─{mysqld}(755)
           │             ├─{mysqld}(756)
           │             ├─{mysqld}(757)
           │             ├─{mysqld}(761)
           │             ├─{mysqld}(762)
           │             ├─{mysqld}(763)
           │             ├─{mysqld}(764)
           │             ├─{mysqld}(765)
           │             ├─{mysqld}(766)
           │             ├─{mysqld}(767)
           │             ├─{mysqld}(768)
           │             ├─{mysqld}(770)
           │             ├─{mysqld}(771)
           │             ├─{mysqld}(778)
           │             ├─{mysqld}(779)
           │             ├─{mysqld}(783)
           │             ├─{mysqld}(790)
           │             ├─{mysqld}(792)
           │             ├─{mysqld}(797)
           │             └─{mysqld}(798)
           ├─networkd-dispat(386)
           ├─nginx(567)───nginx(568)
           ├─pdns_server(773)─┬─{pdns_server}(780)
           │                  ├─{pdns_server}(781)
           │                  ├─{pdns_server}(782)
           │                  ├─{pdns_server}(784)
           │                  ├─{pdns_server}(785)
           │                  ├─{pdns_server}(786)
           │                  ├─{pdns_server}(788)
           │                  ├─{pdns_server}(789)
           │                  └─{pdns_server}(791)
           ├─polkitd(451)─┬─{polkitd}(473)
           │              └─{polkitd}(475)
           ├─rsyslogd(390)─┬─{rsyslogd}(426)
           │               ├─{rsyslogd}(427)
           │               └─{rsyslogd}(428)
           ├─snapd(1064)─┬─{snapd}(1071)
           │             ├─{snapd}(1072)
           │             ├─{snapd}(1073)
           │             ├─{snapd}(1074)
           │             ├─{snapd}(1078)
           │             ├─{snapd}(1079)
           │             ├─{snapd}(1230)
           │             ├─{snapd}(1231)
           │             └─{snapd}(1235)
           ├─sshd(565)───sshd(826)───sshd(925)───bash(926)───sudo(937)───sudo(938)───bash(939)───pstree(2903)
           ├─systemd(843)───(sd-pam)(844)
           ├─systemd-journal(112)
           ├─systemd-logind(397)
           ├─systemd-network(323)
           ├─systemd-resolve(325)
           ├─systemd-udevd(154)
           └─unattended-upgr(439)───{unattended-upgr}(484)

Linuxの起動プロセス

電源を入れてからの起動プロセスは以下のようになります。
このinitのところがsystemdに該当します。

スクリーンショット 2024-02-27 23.53.51.png

unit

systemdにおいて、各種のリソースはunitとして管理されます。
unitの状態を切り替えたり、unit間の依存関係を計算したりすることによって、リソースを管理することができます。
ここでいうリソースとは、「サーバーの管理」や「ネットワーク接続要求の管理」や「ファイルマウントシステムの管理」などさまざまです。

unitには複数のタイプが存在しており、現在では11種類あります。

起動中のLinuxにおいて、現在systemdが扱っているunitの一覧は以下のコマンドで確認することができます。

$ systemctl list-units

unitの状態

unitは状態をもち、基本的にはactiveもしくはinactiveです。
中間状態としてactivatingdeactivating, reloadingがあります。
unitの状態はsystemctl statusで確認することができます。

$ systemctl status UNIT_NAME

# ex.
$ systemctl status isupipe-ruby.service 
● isupipe-ruby.service - isupipe-ruby
     Loaded: loaded (/etc/systemd/system/isupipe-ruby.service; enabled; vendor preset: enabled)
     Active: active (running) since Tue 2024-02-27 18:29:30 UTC; 4min 45s ago
   Main PID: 2793 (bundle)
      Tasks: 57 (limit: 1121)
     Memory: 203.5M
        CPU: 2.000s
     CGroup: /system.slice/isupipe-ruby.service
             ├─2793 "puma 6.4.0 (tcp://0.0.0.0:8080) [ruby]" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" >
             ├─2794 "puma: cluster worker 0: 2793 [ruby]" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" >
             ├─2795 "puma: cluster worker 1: 2793 [ruby]" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" >
             ├─2796 "puma: cluster worker 2: 2793 [ruby]" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" >
             ├─2797 "puma: cluster worker 3: 2793 [ruby]" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" >
             ├─2798 "puma: cluster worker 4: 2793 [ruby]" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" >
             ├─2799 "puma: cluster worker 5: 2793 [ruby]" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" >
             ├─2805 "puma: cluster worker 6: 2793 [ruby]" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" >
             └─2806 "puma: cluster worker 7: 2793 [ruby]" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" >

Job

systemdにおいて、状態を変更するためにunitに対して行う操作をJobと呼んでいます。
start, stop, restart, reloadがあります。
(systemctl start UNIT_NAME, systemctl stop UNIT_NAME...etc)

unitの依存関係

systemdではunit間に依存関係を構築することができます。
アプリケーションサーバを立ち上げる際に、DBサーバが先に立ち上がっていて欲しいなどの依存関係などです。
特定のunitが、どのような依存関係を持っているのかはsystemctl list-dependenciesで確認することができます。

$ systemctl list-dependencies isupipe-ruby.service 
isupipe-ruby.service
● ├─-.mount
● ├─mysql.service
● ├─system.slice
● └─sysinit.target
●   ├─apparmor.service
●   ├─blk-availability.service
●   ├─dev-hugepages.mount
●   ├─dev-mqueue.mount
●   ├─finalrd.service
# ...

unit file

unitunit fileという設定ファイルによって管理されます。

unit fileの見方

例として、isucon13のRuby実装のunit fileを見てみます。
/etc/systemd/system/isupipe-ruby.serviceにあり、こちらでは、Rubyのアプリケーションサーバ(puma)のunitが管理されています。

systemctl catを使うと、特定のunitに対応するunit fileを表示してくれるので便利です。

$ systemctl cat isupipe-ruby.service 
# /etc/systemd/system/isupipe-ruby.service
[Unit]
Description=isupipe-ruby
After=syslog.target
After=mysql.service
Requires=mysql.service

[Service]
WorkingDirectory=/home/isucon/webapp/ruby
Environment=RUBY_YJIT_ENABLE=1
EnvironmentFile=/home/isucon/env.sh

User=isucon
Group=isucon
ExecStart=/home/isucon/.x bundle exec puma --bind tcp://0.0.0.0:8080 --workers 8 --threads 0:8 --environment production
ExecStop=/bin/kill -s QUIT $MAINPID

Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

[Unit], [Service], [Install]はセクションで、各ディレクティブをグルーピングして整理するためのものです。

[Unit]

Description

unitに対してつける短いタイトル・ラベルです。
systemctl statusを実行したときなどに表示されます。

Requires

unitの依存関係を示すためのディレクティブです。
対象のunitを有効化する場合、Requiresに指定したunitも同時に有効化するようになります。

似たディレクティブにWantsがありますが、これは依存度の違いです。
Wantsは、依存関係にあるunitの有効化が失敗しても対象のunitに影響はありませんが、Requiresの場合、依存関係にあるunitの有効化が失敗すると対象のunitの有効化も失敗します。

Wants, Requireは依存関係を指定するためのもので、順序関係を保証するものではありません。
次のAfterを指定することによって、順序関係を構築することができます。

After

Afterディレクティブには、先に有効化されていて欲しいunitを指定します。
アプリケーションサーバを立ち上げる前に、dbサーバが立ち上がっていて欲しいので、この例では、mysql.serviceが指定されています。

[Service]

ExecStart

serviceがスタートした時(systemctl startの実行時)に実行されるコマンドです。
この例では、pumaのアプリケーションサーバを起動しています。

ExecStop

serviceを終了した時(systemctl stopの実行時)に実行されるコマンドです。

Restart

serviceがexitした時、killされた時、timeoutした時などにリスタートするかどうかを指定します。
各値と、いつリスタートするかの関係は以下になります。(Xがリスタートするの意味)

┌─────────────────────────────┬────┬────────┬────────────┬────────────┬─────────────┬──────────┬─────────────┐
│Restart settings/Exit causes │ no │ always │ on-success │ on-failure │ on-abnormal │ on-abort │ on-watchdog │
├─────────────────────────────┼────┼────────┼────────────┼────────────┼─────────────┼──────────┼─────────────┤
│Clean exit code or signal    │    │ X      │ X          │            │             │          │             │
├─────────────────────────────┼────┼────────┼────────────┼────────────┼─────────────┼──────────┼─────────────┤
│Unclean exit code            │    │ X      │            │ X          │             │          │             │
├─────────────────────────────┼────┼────────┼────────────┼────────────┼─────────────┼──────────┼─────────────┤
│Unclean signal               │    │ X      │            │ X          │ X           │ X        │             │
├─────────────────────────────┼────┼────────┼────────────┼────────────┼─────────────┼──────────┼─────────────┤
│Timeout                      │    │ X      │            │ X          │ X           │          │             │
├─────────────────────────────┼────┼────────┼────────────┼────────────┼─────────────┼──────────┼─────────────┤
│Watchdog                     │    │ X      │            │ X          │ X           │          │ X           │
└─────────────────────────────┴────┴────────┴────────────┴────────────┴─────────────┴──────────┴─────────────┘
RestartSec

serviceをリスタートする際に、どれだけスリープを入れるかを指定します。

[Install]

WantedBy

systemctl enableを実行したときに、指定したunit.wantsディレクトリにシンボリックリンクが貼られます。

$ sudo systemctl enable isupipe-ruby.service 
Created symlink /etc/systemd/system/multi-user.target.wants/isupipe-ruby.service → /etc/systemd/system/isupipe-ruby.service.

$ ls -l /etc/systemd/system/multi-user.target.wants/isupipe-ruby.service 
lrwxrwxrwx 1 root root 40 Feb 27 20:01 /etc/systemd/system/multi-user.target.wants/isupipe-ruby.service -> /etc/systemd/system/isupipe-ruby.service

multi-user.targetはLinuxの起動時に実行されるunitであるため、これに対して依存関係を持つことで、起動時にこのunitも自動で有効化されます。

unit fileのpath

特定のpathにunit fileを配置することによってsystemdに認識させることができます。

  • /lib/systemd/system
    • パッケージマネージャによってインストールされたユニット
  • /etc/systemd/system
    • 管理者の操作によって作成されるユニット
  • /run/systemd/system
    • 実行時に自動的に作成されるユニット

↑ の3箇所ありますが、直接編集するユニットは/etc/systemd/systemに配置します。

参考

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?