SysV init方式におけるランレベル

systemdが普及する以前の伝統的なLinuxでは、SysV initという仕組みが、システムの起動状態を管理していました。SysV initでは、システムの状態を0から6までのランレベルという番号で表します。

ランレベル一般的な意味
0システムの停止(poweroff)
1(s・Sも同様)シングルユーザモード(レスキューモード)
2〜4マルチユーザモード(ディストリビューションにより用途が異なる)
5マルチユーザモード+グラフィカルログイン(多くのディストリビューションでの慣例)
6システムの再起動(reboot)

/etc/inittab・init・telinit

SysV init方式では、/sbin/init(PID 1のプロセス)が、/etc/inittabファイルの記述に従って起動時の処理を決定します。/etc/inittabには、id:ランレベル:アクション:プロセスという形式の行が並び、initdefaultという特殊なアクションを持つ行で、システム起動時に入る既定のランレベルを指定します。

id:3:initdefault:

稼働中のシステムのランレベルを変更したい場合は、telinitコマンドを使ってinitへランレベルの変更を指示します。

telinit 1

上の例は、稼働中のシステムをランレベル1(シングルユーザモード)へ切り替えます。通常は、/etc/inittabのrc関連エントリからランレベルごとのrcスクリプトが呼び出され、/etc/rcN.d/配下のS・Kリンクに従って、/etc/init.d/配下のサービスごとの起動スクリプトが実行されます。これにより、ランレベルが切り替わるたびに必要なサービスの起動・停止が行われます/etc/init.d/配下のスクリプトを使った個々のサービスの有効化・無効化については「ホストのセキュリティ設定」の技術解説記事で扱っています。[1]。

systemdへの移行とブートターゲット

現在の主要なディストリビューションの多くは、PID 1の実装としてsystemdを採用しています。systemd環境でも/sbin/initはsystemdを指すシンボリックリンクとなっていることが一般的です採用状況はディストリビューションやバージョンによって異なり得るため、「すべてのディストリビューションが必ずsystemdを採用している」と断定はできません。あくまで広く採用されている代表例としてご理解ください。[2]。systemdでは、SysV initの「ランレベル」に相当する概念をターゲット(target)という単位で表します。後方互換性のため、伝統的なランレベル番号は、次のようにsystemdのターゲットへ対応付けられています。

ランレベル対応するsystemdターゲット
0poweroff.target
1rescue.target
2・3・4multi-user.target
5graphical.target
6reboot.target

ランレベル2〜4は、いずれもmulti-user.targetという同じターゲットに対応付けられています。これは、systemdの観点ではこれらのランレベルが機能的に区別されていないためです。また、runlevel1.targetのように、ランレベル番号を含む名前が各ターゲットのエイリアス(別名)として用意されており、SysV init時代の慣習に沿った指定方法も一応使えるようになっています。

/etc/systemd/と/usr/lib/systemd/

systemdの動作を定義するユニットファイル(サービスやターゲットの定義)は、複数のディレクトリに分かれて置かれます。代表的な検索先と優先順位は次のとおりです。

ディレクトリ内容
/etc/systemd/system/管理者が作成・変更するユニットファイル(最優先)
/run/systemd/system/実行時に生成される一時的なユニットファイル
/usr/local/lib/systemd/system/管理者がローカルにインストールしたユニットファイル
/usr/lib/systemd/system/または/lib/systemd/system/ディストリビューションのパッケージが提供するユニットファイル(既定の内容)

ディストリビューションにより、パッケージ提供ユニットの配置先は/usr/lib/systemd/system/または/lib/systemd/system/となります。同じ名前のユニットファイルが複数の場所に存在する場合、より優先順位の高いディレクトリにあるものが使われます。この仕組みにより、パッケージ提供ファイルを直接書き換えなくても、/etc/systemd/system/側に変更後の内容を置くことで、管理者が動作を上書き(オーバーライド)できます。

デフォルトのブートターゲットを設定する

システム起動時に既定でどのターゲットに入るかは、systemctl get-default・systemctl set-defaultコマンドで確認・変更します。

コマンド内容
systemctl get-default現在設定されている既定のブートターゲットを表示する
systemctl set-default ターゲット名既定のブートターゲットを変更する
systemctl get-default
systemctl set-default multi-user.target

systemctl set-defaultは、内部的にはdefault.targetという特別な名前のシンボリックリンクを、指定したターゲットへ張り替える処理です。この設定が反映されるのは次回起動時からであり、現在稼働中のシステムのターゲットがその場で切り替わるわけではありません。

ブートターゲット(シングルユーザモードを含む)を変更する

稼働中のシステムのターゲットをその場で切り替えたい場合は、systemctl isolateコマンドを使います。

systemctl isolate rescue.target

isolateは、AllowIsolate=yesが設定された指定ターゲットとその依存関係にあるユニットだけを起動し、それ以外のユニットを停止するというコマンドです。「次回起動時の既定値を変える」set-defaultと、「今すぐ現在の状態を切り替える」isolateは、まったく別の操作である点に注意してください稼働中のシステムをシングルユーザモードへ切り替えたい場合、systemctl set-default rescue.targetを実行しても、次回起動時の設定が変わるだけで、今すぐシングルユーザモードには切り替わりません。systemctl isolate rescue.target(または、同等のショートカットであるsystemctl rescue)を使う必要があります。[3]。

rescue.targetとemergency.targetの違い

シングルユーザモードに相当するターゲットとして、rescue.targetのほかにemergency.targetがあります。

ターゲット内容
rescue.target基本的なシステムマウント等を行ったうえで、レスキューシェルを起動する
emergency.target通常のサービスや追加のマウント処理を行わず、コンソール上に緊急用のシェルのみを起動する(起動に問題がある場合の最終手段)

シングルユーザモードに相当するターゲットとしては、rescue.targetを指定します。カーネルの起動オプションでレスキューモードを指定する場合は、systemd.unit=rescue.targetを指定します。singleやsingle.targetの互換的な扱いは、ディストリビューションやsystemdのバージョンによって異なる場合があるため、rescue.targetを使うようにしてくださいsystemctl set-default rescue.targetのように、systemdで定義されているターゲット名を指定します。[4]。

コマンドラインからシャットダウンおよびリブートする

shutdownコマンド

shutdownは、システムを安全に終了・再起動するための、伝統的なコマンドです。

shutdown [オプション] [時刻] [メッセージ]
オプション・引数内容
-hシャットダウン後にシステムを停止し、通常は電源も切る
-Hシャットダウン後にシステムを停止する(電源は切らない)
-Pシャットダウン後にシステムを停止したうえで、電源も切る
-rシャットダウン後にシステムを再起動する
-c予約済みのシャットダウンを取り消す
now直ちに実行する(+0と同じ)
+分数指定した分数だけ待ってから実行する
時:分指定した時刻(24時間表記)に実行する
shutdown -r +10 "10分後に再起動します。作業を保存してください。"
shutdown -c

時刻を指定した場合、その後に続けて指定したメッセージが、ログイン中の全ユーザーへ警告として配信されますメッセージだけを単独で指定することはできず、メッセージを付ける場合は時刻の指定も必要です。[5]。

halt・reboot・poweroffコマンド

shutdownのオプションを使わずに、直接システムを停止・再起動するコマンドとして、halt・reboot・poweroffもあります。

コマンド内容
haltシステムを停止する(電源は切らない)
poweroffシステムを停止したうえで、電源も切る
rebootシステムを再起動する

現在のsystemd環境では、halt(電源は切らずに停止のみ)とpoweroff(電源を切るところまで行う)は明確に区別されています歴史的には、haltが事実上poweroffと同じ動作をする環境もありましたが、systemd環境ではこの2つの役割が明確に分けられています。「haltとpoweroffは常に同じ動作をする」と一律に断定しないようにしてください。[6]。いずれのコマンドも、-f(--force)オプションを1回付けると、サービスユニットを順序立てて停止せずに処理を進めます。ただし、この場合でも、プロセスの強制終了やファイルシステムのアンマウントまたは読み取り専用での再マウントは行われます。-fを2回付けた場合は、プロセスの終了やファイルシステムのアンマウントも行わずに即時実行します。緊急時以外での多用は推奨されません。

wallによるユーザーへの警告

wallは、ログイン中の全ユーザーの端末へ、任意のメッセージを一斉に表示するコマンドです。

wall "システムは20時にメンテナンスのため再起動します。"

shutdownコマンドに時刻とメッセージを指定した際に自動的に行われる警告も、内部的にはこのwallの仕組みを利用しています。ランレベル/ブートターゲットの切り替えや、システムの停止・再起動といった重要なイベントの前には、ログイン中の他のユーザーに影響が及ぶ可能性があるため、事前にwall等で警告することが望まれます。

シャットダウン時のプロセスの終了

システムをシャットダウンする際、systemdはまず、依存関係に基づいて各サービス(ユニット)を順序立てて正常に停止させます。それでも残ってしまったプロセスやマウントされたファイルシステムについては、最終段階として一括で強制的に後始末(プロセスの終了、ファイルシステムのアンマウント等)を行う、という2段階の仕組みになっています。-f(--force)オプションを1回付けたhalt・reboot・poweroffは、この最初の「順序立てた正常な停止」の段階を飛ばしますが、プロセスの強制終了やファイルシステムの後始末は行われます。-fを2回指定すると、プロセスの終了やファイルシステムのアンマウントも行われないため、ファイルシステムが破損するおそれがある点に注意してください。

systemd-analyzeによる起動時間の分析

systemd-analyzeは、システムの起動にかかった時間を分析するためのコマンドです。

サブコマンド内容
systemd-analyze(引数なし。timeと同じ)ファームウェア・ブートローダー(利用可能な場合)・カーネル・initrd・ユーザースペースの起動所要時間の内訳を表示する
systemd-analyze blame各ユニットの初期化にかかった時間を、時間のかかった順に一覧表示する
systemd-analyze critical-chain起動完了までの所要時間を左右した、依存関係の連鎖(クリティカルチェーン)を表示する
systemd-analyze
systemd-analyze blame

起動が遅いと感じた場合に、blameでどのユニットの初期化に時間がかかっているかを特定し、critical-chainでその依存関係の流れを確認する、という使い方が一般的です。

参考:acpidについての基礎知識

出題範囲には「acpidについての知識」も含まれています。acpidは、電源ボタンが押された、ノートPCの液晶を閉じた、といったACPI(電源管理に関するハードウェアの規格)イベントをカーネルから受け取り、あらかじめ設定されたスクリプトを実行するデーモンです。例えば、電源ボタンが押された際に安全なシャットダウン処理を実行する、といった設定に使われます。現在の多くのシステムでは、電源ボタン等の標準的なイベントはsystemd-logind(/etc/systemd/logind.confで設定)が処理するようになっており、acpidは、それだけではカバーしきれない、より複雑・独自のイベント処理が必要な場合に別途導入される位置づけになっています「acpidが無いと電源ボタンのイベントを一切処理できない」というわけではなく、標準的な範囲であればsystemd-logindだけでも処理できる点に注意してください。[7]。


補足

  1. /etc/init.d/配下のスクリプトを使った個々のサービスの有効化・無効化については「ホストのセキュリティ設定」の技術解説記事で扱っています。 ↩
  2. 採用状況はディストリビューションやバージョンによって異なり得るため、「すべてのディストリビューションが必ずsystemdを採用している」と断定はできません。あくまで広く採用されている代表例としてご理解ください。 ↩
  3. 稼働中のシステムをシングルユーザモードへ切り替えたい場合、systemctl set-default rescue.targetを実行しても、次回起動時の設定が変わるだけで、今すぐシングルユーザモードには切り替わりません。systemctl isolate rescue.target(または、同等のショートカットであるsystemctl rescue)を使う必要があります。 ↩
  4. systemctl set-default rescue.targetのように、systemdで定義されているターゲット名を指定します。 ↩
  5. メッセージだけを単独で指定することはできず、メッセージを付ける場合は時刻の指定も必要です。 ↩
  6. 歴史的には、haltが事実上poweroffと同じ動作をする環境もありましたが、systemd環境ではこの2つの役割が明確に分けられています。「haltとpoweroffは常に同じ動作をする」と一律に断定しないようにしてください。 ↩
  7. 「acpidが無いと電源ボタンのイベントを一切処理できない」というわけではなく、標準的な範囲であればsystemd-logindだけでも処理できる点に注意してください。 ↩