LinuxのランレベルとSystemdについて
LinuxのランレベルやSystemdについての覚書です。
Linuxのランレベル
Windowsにも通常起動とセーフモードがあったりしますが、それに似ています。それぞれのレベルに対してサービスのON、OFFが設定されています。3と5の違いで考えるとわかりやすいかもしれません。GUIに必要なサービスはランレベル3では動きませんが、5では動きます。1の時はWindowsのセーフモードと同じように最低限のサービスしか動きません。
- 0
停止
- 1
シングルユーザ(ネットワークなし)
- 2
マルチユーザ(NFSマウントなし)
- 3
CUIマルチユーザ
- 4
ユーザー定義
- 5
GUIマルチユーザ
- 6
再起動
/sbin/init コマンドはランレベルの変更をします。ここで引数0を与えると、ランレベルが0の停止に変更されます。つまり即座にシャットダウンされます。
Systemd
SystemdはLinuxを起動する方法のひとつで、歴史をたどるとSysVinit→Upstart→Systemdとなるようです。
電源ONからinitプロセスに至るまではBIOS/UEFI起動→GRUB→カーネル起動→initプロセス起動となります。
従来のSysVinitではinitプロセス起動後、ランレベルに合わせて登録済みのユーザプロセスを順に読み込んでいました。これはシーケンス(直列)処理なので時間がかかりました。
それを改良したUpstartではユーザープロセスを並列化させて処理することで速度を上げました。その際イベント管理で依存関係を判別したのですが、イベントの管理が大変で無駄も発生しました。
そこから進化したSystemdではイベントという概念から離れて、ジョブではなくユニットという単位で管理することにより、さらなる高速化や設定の簡易化が実現しました。
SystemdではSysVini時代の個々の処理がユニットとして個々に登録されています。ユニットのタイプには次のようなものがあります。
- service
サービス
- target
複数のユニットがグループ化されたもの
- mount
デバイスのマウント
- swap
Swap領域の有効化
- device
他デバイス
- socket
systemdが特定のsocketがlistenし接続があると指定したデーモンを起動してソケットを渡すxintedのような機能です。xintedとはスーパーデーモンと呼ばれ、仕事のないデーモンが休止状態に入れるように、すべてのデーモンへの要求を代わりに待機するデーモンです。
serveiceやtargetは明示的に記述する必要があります。mountやswapは/etc/fstab処理時に自動生成され、deviceはudevの処理で自動生成されます。
Systemdの依存関係と順序
Systemdでは依存関係のないものは並列処理されます。依存関係をSystemdに知らせる方法は2つあって、ひとつは「Wants= 」「Require=」というふうにファイルへ記述する方法、もうひとつは「ユニット名.wants」や「ユニット名.requires」というディレクトリをつくり、そこへ実際のユニットへのシンボリックリンクを張る方法です。
wantsは指定したユニットが失敗してもメインのユニットを実行します。一方のrequiresは失敗すればメインのユニットは実行しません。他に「Conflict」を指定すると、同時に起動しないユニットも指定できます。
依存関係とは別に起動順序が存在しこちらは「Before」「After」で指定します。
Systemdの設定ファイルの配置場所
通常/etc/systemd/systemディレクトリに設定ファイルを置けばサービスとして認識してくれます。ただ、デフォルトの設定ファイルの多くは/usr/lib/systemd/systemに存在し、ここに記述した設定ファイルも読み込まれます。
後者は初期インストール時などのデフォルトの設定ファイルが入ることとなっており、ユーザーが記述するファイルは/etc/systemd/systemに置くことになっています。
ふたつのフォルダで、同じ名前の設定があった場合は/etc/systemd/system側が優先されます。
また筆者の環境では上記のふたつ以外のディレクトリに設定ファイルを保存し/etc/systemd/systemからシンボリックリンクを貼るという運用になっているものもありました。たとえばsyslog.serviceは/lib/systemd/systemディレクトリに存在しました。
Systemdの設定ファイルの記述
ファイル内は[Unit][Service][Install]のセクションに分かれています。サンプルとして筆者がインストールしたapache2のファイルapache2.serviceを使って説明します。
Unitセクションには先の依存関係やDescription=説明などが入ります。
[Unit] Description=The Apache HTTP Server After=network.target remote-fs.target nss-lookup.target Documentation=https://httpd.apache.org/docs/2.4/
Serviceセクションにはサービスの起動、終了等様々な項目が存在します。
- Type:起動成功の判別方法
デフォルトはsimpleです。ExecStartに指定したコマンドがメインプロセスになる場合等に使います。起動後すぐに成功が帰ります。forkingはバックグラウンドへフォークした子プロセスがメインプロセスになる場合に使います。子プロセスの最初のコマンドが完了した後に成功が帰ります。
- Environment:環境変数の設定
- ExecStart:開始コマンド
- ExecStop:終了コマンド
- Reload=設定ファイルの再読み込み
- PrivateTmp=専用の/tmp /var/tmpを用意するか
この設定がある時のみreloadコマンドが使えます。
- Restart=再起動時のモード
always、on-abort等の文字で、停止処理の成否で再起動するかしないかを決めます。
[Service] Type=forking Environment=APACHE_STARTED_BY_SYSTEMD=true ExecStart=/usr/sbin/apachectl start ExecStop=/usr/sbin/apachectl stop ExecReload=/usr/sbin/apachectl graceful PrivateTmp=true Restart=on-abort
Installセクションにはdisabled/enabled(後述参照)をした際の挙動を書きます。WantedBy=にユニットを書いておくと、unitを有効化した際に、記述したユニット.wantsディレクトリに自ユニットのシンボリックリンクが入ります。
よくある設定だとWantedBy=multi-user.targetが記述されています。こうするとmulti-user.target起動時に、自ユニットも起動要求がかかるようになります。multi-user.targetはシステム起動時に起動されますので、スタートアップ時に起動されるということにもなります。
同様にRequiredByも記述が可能です。
Alsoを指定しておくと、ユニットが有効無効化されたときに指定したユニットも同期します。
サービスを自作する場合はサフィックスを.serviceとして、/etc/systemd/systemに配置します。
Sytemdの基本操作
- systemctl list-dependencies ユニット名
依存関係の確認。ユニット名を省略するとdefault.targetとなります。オプションとして--befeor、--afeter、--allがとれます。
- systemctl enbale/disable ユニット名
有効化と無効化。
- systemctl start/stop/restart ユニット名
起動と停止、再起動。
- systemctl status ユニット名
現在の状態。
- systemctl daemon-reload
unitファイルの変更を反映。
- systemctl list-unit-files --type=service
サービス一覧を出力。
参考にさせていただいたサイト
今回参考にさせていただきましたサイト様です。ありがとうございました。