System Initについて：systemd、SystemVとUpstart

はじめに

第39章はじめに

このビデオでは、この章で説明するトピックの概要を簡単に説明します。


学習目標
この章の終わりまでに、次のことができるようになります。

初期化プロセスの重要性を理解できます。
systemd（およびUpstart）がどのように起動し、どのように機能するかを理解できます。
systemctlを使用して、systemdを構成および制御できます。
従来のSysVinitメソッドがどのように機能し、ランレベルがどのように組み込まれ、それぞれで何が起こるかを説明できます。
SysVinitを使用している時に、chkconfigとservice（および代替ユーティリティ）を使用して、サービスの開始・停止や再起動後の設定の恒久化を行うことができます。


System Init

initプロセス
/sbin/init（通常は単にinitと呼ばれます）は、システムで実行される最初のユーザー レベルのプロセス（またはタスク）であり、システムがシャットダウンされるまで実行を続けます。従来、すべてのユーザー プロセスの親と見なされてきましたが、技術的にはそうではありません。一部のプロセスはカーネルによって直接開始されるためです。

initは、ブート プロセス後の処理を統合し、あらゆる環境を設定し、システムへのログインに必要なプロセスを開始します。initは、プロセス終了後にクリーン アップを行う際にもカーネルと密接に連携します。

従来、ほぼすべてのディストリビューションは、UNIXの由緒あるSysVinitソフトウェアのinitプロセスをベースにしていました。しかしながら、このスキームは数十年前に、かなり異なる状況下で開発されたものでした。

ターゲットはマルチ ユーザー メインフレーム システムでした（パーソナル コンピュータ、ラップトップ、その他のデバイスではありませんでした）
さらにターゲットはシングル プロセッサ システムでした。
そのため、起動（およびシャットダウン）時間は重要な問題ではありませんでした。物事を正しく動作させる方がはるかに重要でした。

起動は、一連の順次処理に分割された連続プロセスと見なされていました。次のステップに進む前に、現在のステージを完了する必要がありました。したがって、起動処理に、複数のプロセッサまたはコアで実行する並列処理を、簡単には活用できませんでした。

さらに、シャットダウン／再起動は比較的まれなイベントと見なされており、正確にどのくらい時間がかかるかは重要ではありませんでした。

最新のシステムでは、機能を強化した新しいメソッドが必要です。


起動方法の選択肢
SysVinitにおける、これらの固有の制限に対処するために、システムの起動を制御する新しい方法が開発されました。他にもありますが、エンタープライズ ディストリビュータは、upstartとsystemdの2つの主要なスキームを採用しました。

クリックして各ボックスを展開し、upstartとsystemdについて学習します。

起動方法の選択肢

Upstart
UpstartはUbuntuによって開発され、2006年の6.10リリースで最初に組み込まれ、2009年の9.10リリースでデフォルトになりました。また、Fedora 9（2008年）、RHEL 6やそのクローン（CentOS、Scientific Linux、Oracle Linuxなど）とopenSUSEでも採用されました。さまざまな組み込み機器やモバイル機器でも使用されています。

systemd
systemdはもっとも最近開発されたものであり、主要なディストリビューションの中では、Fedoraが 最初に2011年に採用しました。RHELとSUSEは 今ではSystemdを採用しており、Ubuntu 16.04はUpstartをsystemdに置き換えました。

他のすべての主要な Linux ディストリビューションもsystemdを採用し、デフォルトとして設定しています。systemdの主要開発者は、Linuxカーネル コミュニティと密接に連携しています。今では、Ubuntuでさえ、Upstartを廃止しました。

systemdへの移行は簡単ではなく、バグや欠落している機能が無効になる可能性があるため、必須なものとして互換性レイヤーが採用されました。したがって、SysVinitのユーティリティとメソッドは、たとえ内部の状況がまったく異なっていても存続しています。

systemdの開発と採用の歴史はかなり複雑であり、変化にとんだ個性は、すべての議論が技術的な性質のものではなかったことを物語っています。

次は、systemdとSysVinit中心に説明します。もはやほとんど使用されなくなったUpstartは説明しません。


systemdの機能
Linuxのsystemdシステムとセッション マネージャは、今やすべての主要なディストリビューションで主流です。次の機能が含まれています。

以前のinitシステムよりも高速に起動します。
積極的に並列化機能を提供します。
サービスの開始にソケットとD-Busアクティベーションを使用します。
シェル スクリプトをプログラムに置き換えます。
デーモンのオンデマンド起動を提供します。
cgroupsを使用してプロセスを追跡します。
マウントと自動マウントのポイントを保持します。
精巧なトランザクションの依存関係に基づくサービス制御ロジックを実装します。
SysVinitの一時的な代替として機能し、SysVinitスクリプトと互換性があります。

bashスクリプトの代わりに、systemdは.serviceファイルを使用します。さらに、systemdはすべてのデーモンを独自のLinux cgroup（制御グループ）に分類します。

systemdはSysVinitと後方互換性があり、systemdではランレベルの概念はランレベル ターゲットを介してサポートされていることに注意してください。telinitプログラムは、ランレベルで動作するようにエミュレートされます。


systemdの構成ファイル
systemdは標準化された構成ファイルのセットを使用することを推奨していますが、代替としてディストリビューション依存のレガシー構成ファイルを使用することもできます。

新しい構成ファイルの例は/etc/hostnameで、Red Hatの/etc/sysconfig/network、SUSEの/etc/HOSTNAME、Debianの/etc/hostname（標準として採用）を置き換えます。

他のファイルとして、次のものがあります。

/etc/vconsole.conf：デフォルトのキーボード マッピングとコンソール フォント。
/etc/sysctl.d/*.conf：カーネル sysctlパラメーターのドロップイン ディレクトリ。
/etc/os-release：ディストリビューションIDファイル。

systemdはSysVinitと後方互換性があるため、古いコマンドを使用してもほとんどの場合機能します。ランレベル ターゲットのメカニズムを介して、概念的にはランレベルの使用をサポートしています。さらに、telinitはランレベルで動作するようにエミュレートされます。


systemctl
systemctlは、サービスを管理するための主要なユーティリティです。基本的な構文は次のとおりです。

$ systemctl [options] command [name]

以下に、systemctlの使用方法の例をいくつか示します。

systemdが制御するすべての状態を表示する場合：

$ systemctl

利用可能なすべてのサービスを表示する場合：

$ systemctl list-units -t service --all

アクティブなサービスのみを表示する場合：

$ systemctl list-units -t service

1つ以上のユニットを開始（アクティブ化）または停止（非アクティブ化）する場合：

$ sudo systemctl start foo
$ sudo systemctl start foo.service
$ sudo systemctl start /path/to/foo.service
$ sudo systemctl stop foo.service

ユニットはサービスまたはソケットにあたります。

サービスを有効／無効にする場合：

$ sudo systemctl enable sshd.service
$ sudo systemctl disable sshd.service

これらのコマンドは、実際にはサービスを開始したり停止したりしません。システムの起動時に起動するかどうかを制御します。

ほとんどのコマンドでは、サービス名に付加された.serviceを省略できます。

💡
上記の例の一部のsystemctlコマンドはrootユーザー以外でも実行できますが、それ以外のコマンドはrootまたはsudoで実行する必要があります。

SysVinitからsystemdへの移行方法については、SysVinitからSystemdへのチートシートを参照してください。


デモ：systemctlの使用

このビデオでは、systemdでサービスを開始、停止、有効化、無効化する方法、およびsystemctlユーティリティの使用方法を示します。


SysVinitのスロー フェード アウト
SysVinitは長年にわたって、システムの起動とシャットダウンの、そしてサービス管理の、標準的な方法でした。

しかし、すべての主要なLinuxディストリビューションではsystemdへの置き換えが進んでいます。置き換えが進む中でも、SysVinitの動作をカバーすることはまだ必要です。古いメソッドを引き続き使用できるようにするため、互換レイヤーが設けられています。サード パーティのソフトウェアが、systemdのsystemctlメソッドを使用するように更新されていない場合もあるためです。

この後、ランレベルや他の構成要素の説明に加えて、chkconfigコマンドとserviceコマンドも説明していきます。


SysVinitのランレベル
SysVinitシステムが起動すると、さまざまなシステム状態を定義するランレベルのシーケンスを通過します。それらには0から6までの番号が付けられています。

ランレベル0はシステム停止状態用、ランレベル1はシングル ユーザー モード用、ランレベル6はシステム リブート用に予約されています。他のランレベルは、通常のシステムで実行されているサービスを定義するために使用されます。たとえば、Red Hatベースのシステムでは、ランレベル2はネットワークまたはXを使用しない実行中のシステムとして定義されています。ランレベル3はネットワークを含んだもの、ランレベル5はネットワークとXを含んだものになります。以下の表は、SystemVinitのランレベルをまとめたものです。

表：SysVinit のランレベル

ランレベル　　意味
S,s　　 1と同じ
0	システムをシャットダウンして電源を切る
1	シングル ユーザー モード
2	マルチ ユーザー、NFSなし、テキスト ログインのみ
3	マルチ ユーザー、NFSとネットワークあり、テキスト ログインのみ
4	未使用
5	マルチ ユーザー、NFSとネットワークあり、Xによるグラフィカル ログイン
6	再起動
 
現在のランレベルは、次のようにランレベル コマンドで簡単に表示できます。

$ runlevel
N 5

ここで、最初の文字は1つ前のランレベルです。Nは不明を意味します。

telinitを使用して、システムのランレベルを変更できます。たとえば、ランレベル3からランレベル5に変更するには、次のように入力します。

$ sudo /sbin/telinit 5

systemdはランレベルではなくターゲットで動作しますが、多くの経験豊富なユーザーと管理者は（SysVinitの）命名法に慣れているため、systemdはほとんどの場合、同等の後方互換言語に対応できるようになっています。


SysVinit起動スクリプト
従来の方法では、最初にrc.sysinitスクリプトを実行します。このスクリプトは、LVMの起動、ファイルシステムのマウントなど、多くの機能を実行します。このスクリプトは/etcディレクトリにありますが、/etcへのシンボリックリンクを持つ/etc/rc.dにある可能性も高いです。

次に、（同じディレクトリにある）rcスクリプトが、希望するランレベルを引数にして実行されます。これにより、システムはrc.d/rc[0-6].dディレクトリに移動し、そこにあるすべてのスクリプトを次のように実行します。

$ ls -lF /etc/rc.d/rc5.d
total 0l
rwxrwxrwx. 1 root root 14 Sep 3 10:05 K05pmcd -> ../init.d/pmcd*
lrwxrwxrwx. 1 root root 14 Sep 3 10:05 K05pmie -> ../init.d/pmie*
....
lrwxrwxrwx. 1 root root 17 Sep 3 09:39 S10network -> ../init.d/network*
lrwxrwxrwx 1 root root 16 Sep 6 08:50 S19vmware -> ../init.d/vmware*

rc.localスクリプトを使用して、システム固有のアプリケーションを起動します。
:

実際のスクリプトはすべて/etc/init.dにあります。各ランレベル ディレクトリは、それらにリンクが張られています。
そのランレベルになったときに実行されるスクリプトは、名前の頭文字がSになっています。
そのランレベルになったときに終了されるスクリプトは、名前がKで始まります。

ランレベル ディレクトリにスクリプトのシンボリックリンクが存在するかどうかによって、そのランレベルでスクリプトが実行されるかどうかが決まります。

各スクリプト名のKまたはSに続く番号は、スクリプトが呼び出される順序です。スクリプト名はサービスの名前でもあります。

各ランレベルへの入り口で実行される初期化スクリプトの制御には、シンボリックリンクの管理が含まれます。これらのリンクを手動で管理することは可能ですが、それを一貫してより簡単に行えるように設計されたユーティリティとして、chkconfigなどがあります。


chkconfig
chkconfigは、実行するランレベルに応じてさまざまなシステム サービスを照会したり構成したりするために使用されます。以下にいくつかのchkconfigの例を示します。

特定のサービスをチェックして、現在のランレベルで実行するように設定されているかどうかを確認する場合：

$ chkconfig some_service

この場合、サービスが実行されるように構成されていればtrueが、そうでなければfalseが返ります。実行するように構成されていても、現在停止している可能性があることに注意してください。

各ランレベルで実行するように構成されているサービスを確認する場合：

$ chkconfig --list [service names]

次回のシステム ブート時に特定のサービスを有効にする場合：

$ sudo chkconfig some_service on

次回のシステム ブート時に特定のサービスを無効にする場合：

$ chkconfig some_service off

サービスを開始または停止にしても、この有効と無効の指定は現在の状態に影響しないことに注意してください。すぐに状態を変えたい場合：

$ sudo service some_service [stop | start]

独自のサービスを追加して独自の起動スクリプトを作成することは難しくありません。特定の機能を持つ（先頭からの数行のみ！）スクリプトを/etc/init.dに置くだけです。そして、chkconfig --addを使用して有効にするか、chkconfig --delを使用して有効／無効の指示ができないようにします。

chkconfigは、シンボリックリンクでSまたはKの後に表示される番号を実際にどのように決定するのでしょうか？　そして、どのランレベルを有効または無効に設定し、どの状態でシンボリック リンクを設定するかを、どのようにして知るのでしょうか？ その情報はスクリプトの中にあり、最初の方に次のような行が含まれています。

# chkconfig: 2345 10 90

chkconfig:の後の最初の引数は、デフォルトでサービスを有効にするランレベルを定義しています。上記の例では、レベル2、3、4、5を意味します。2番目と3番目の数字は、起動スクリプトと停止スクリプトの数値プレフィックスです。上記の例では、S10とK90で始まるスクリプトを意味します。


service
すべてのオペレーティング システムには、通常、システムの初期化時に開始されるサービスがあり、多くの場合、シャットダウンするまで実行され続けます。このようなサービスはいつでも開始、停止、再起動でき、通常はroot権限が必要です。SysVinitを使用する、またはエミュレートするLinuxシステムでは、サービスは/etc/init.dディレクトリにあるサービスを指します。

特定のサービスの現在の状態を確認するには、次を実行します。

$ sudo service network status
Configured devices:
lo eth0 eth1 eth2 wlan0
Currently active devices:
lo eth0

$ sudo service vsftpd status<
vsftpd (pid 5284) is running...

serviceにはいくつかのオプションがあり、サービスによって異なります。以下に例を示します。

$ sudo service network
Usage: /etc/init.d/network {start|stop|restart|reload|status}

$ sudo service iptables
Usage: /etc/init.d/iptables {start|stop|restart|condrestart|status|panic|save}

どのserviceでも実際に行うことは、ディレクトリを/etc/init.dに変更し、指定されたオプションを使用してそのディレクトリにある適切なスクリプトを実行することです。

システム上のすべてのサービスの状態は、次の方法で確認できます。

$ sudo service --status-all
acpid (pid 4170) is running...
anacron (pid 4540) is running...
atd (pid 4553) is running...
....
smartd (pid 4614) is running...
smbd is stopped
......

serviceによるサービスの開始と停止は、システムで現在操作中の場合にのみ有効です。すべての変更は再起動時に失われます。システムの初期化中に特定のサービスを有効または無効にするには、前述のように、Red Hatベースのシステムではchkconfigを使用する必要があります。


演習

課題 39.1: SysVinitを使って新たなスタートアップ サービスを追加する
🚩
以下のPDFドキュメントに埋め込まれた外部URLにアクセスする場合は、常に右クリックして新しいタブまたはウィンドウで開いてください。直接クリックしてURLを開こうとすると、コース ウィンドウ／タブが閉じます。

【【これ以降は橋本さんの訳を参照】】

In this and the following exercise, we will create a simple startup service.  First we will do it for a SysVinit system.  Note that if you are using a systemd-based system everything should still work because of the backwards compatibility layer that alldistributions utilize. However, in the next exercise we will do natively for systemd.

On Debian -based Distributions

If you are on a Debian-based system like Ubuntu, make sure you have installed the sysvinit-utils and chkconfig packages. However, recent versions of Ubuntu no longer package chkconfig; you’ll have to use the update-rc.d utility instead.

First we have to create the service-specific script; you can create one of your own for fun, or to get the procedure down just (as root) create a file named /etc/init.d/fake_service (which can be extract from your downloaded SOLUTIONS file as fake_service) containing the following:

/etc/init.d/fakeservice

#!/bin/bash
# fake_service
# Starts up, writes to a dummy file, and exits
#
# chkconfig: 35 69 31
# description: This service doesn't do anything.
# Source function library. 

/etc/sysconfig/fake_service

case "$1" in
start) echo "Running fake_service in start mode..."
touch /var/lock/subsys/fake_service
echo "$0 start at $(date)" >> /var/log/fake_service.log
if [${VAR1} ="true" ]
then
echo"VAR1 set to true" >> /var/log/fake_service.log
fi
echo
;;
stop)
echo "Running the fake_service script in stop mode..."
echo "$0stop at$(date)" >> /var/log/fake_service.log
if [${VAR2} ="true" ]
then
echo "VAR2 = true" >> /var/log/fake_service.log
fi
rm -f /var/lock/subsys/fake_service
echo
;;
*)
echo "Usage: fake_service {start | stop}"
exit 1
esac
exit 0

If you are taking the online self-paced version of this course, the script is available for download from your Lab screen.
Make the file above executable and give other proper permissions:

$ sudo chmod 755 /etc/init.d/fake_service

You’ll notice the script includes the file /etc/sysconfig/fakeservice.  (On non-RHEL systems you should change this to /etc/default/fake_service.) Create it and give it the following contents:

/etc/sysconfig/fakeserviceor/etc/default/fakeservice

VAR1="true"
VAR2="true"

Test to see if the script works properly by running the following commands:

$ sudo service fake_service
$ sudo service fake_service start
$ sudo service fake_service stop

Look at the file named/var/log/fake_service.log. What does it contain?

For fun you can add additional modes like restart to the script file; look at other scripts in the directory to get examples of what to do.

Next we will want to have the ability to start fake_service whenever the system starts, and stop it when it shuts down.  If you do:

$ sudo chkconfig --list fake_service

you will get an error as it hasn’t been set up yet for this. You can easily do this with:

$ sudo chkconfig --add fake_service

and you can turn it on or off at boot time with

$ sudo chkconfig fake_service on
$ sudo chkconfig fake_service off

To test this completely you’ll have to reboot the system to see if it comes on automatically.   You can also try varying the runlevels in which the service is running.


課題 39.2: systemdを使って新たなスタートアップ サービスを追加する
🚩
以下のPDFドキュメントに埋め込まれた外部URLにアクセスする場合は、常に右クリックして新しいタブまたはウィンドウで開いてください。直接クリックしてURLを開こうとすると、コース ウィンドウ／タブが閉じます。

Exercise 39.2: Adding a New Startup Service with systemd

As  mentioned  in  the  previous  exercise,  you  can  still  use  the SysVinit startup  script  procedure  with systemd but  this  is deprecated.

The analogous procedure is to create (as root) a file directly under /etc/systemd/system or somewhere else in that directory tree; distributions have some varying tastes on this. For example a very minimal file named /etc/systemd/system/fake2.service (which can be extracted from your downloaded SOLUTIONS file as fake2.service) containing the following:

fake2.service

[Unit]
Description=fake2
After=network.target

[Service]
ExecStart=/bin/sh -c'/bin/echo I am starting the fake2 service ; /bin/sleep 30'
ExecStop=/bin/echo I am stopping the fake2 service

[Install]
WantedBy=multi-user.target

Now there are many things that can go in thisunitfile. The After=network.target means the service should start only after the network does, while the WantedBy=multi-user.target means it should start when we reach multiple-user mode.  Thisis equivalent to runlevels 2 and 3 in SysVinit. Note graphical.target would correlate with runlevel 5.

Now all we have to do to start, stop and check the service status are to issue the commands:

$ sudo systemctl start fake2.service
$ sudo systemctl status fake2.service
$ sudo systemctl stop fake2.service

If you are fiddling with the unit file while doing this you’ll need to reload things with:

$ sudo systemctl daemon-reload

as the system will warn you.
To keep an eye directly on the output you can do:

$ sudo tail -f /var/log/messages

(use/var/log/syslog on Ubuntu) either in background or in another windows while the service is running.
To set things up so the service turns on or off on system boot:

$ sudo systemctl enable fake2.service
$ sudo systemctl disable fake2.service

Once again, you really need to reboot to make sure it has taken effect.


知識チェック

「第39章 - System Initについて：systemd、SystemVとUpstart」を完遂しました。おめでとうございます。このクイズに答えて、これまでに学んだ概念の理解度をチェックしてください。

クイズ開始

問題 39.1
最近まで、ほぼすべてのディストリビューションはSysVinitを使用していました。しかし、SysVinitには問題があり、それがsystemdの開発を後押ししました。その問題について、次のうち正しいものはどれですか？

A. SysVinitは、デスクトップ、組み込みシステム、モバイル プラットフォームとは異なる要件を持つメインフレーム用に設計されました。
B. SysVinitはマルチコア システム用に設計されました。
C. 現在では、起動時間とシャットダウン時間は重要ではありません。
D. SysVinitは信頼できません。
E. systemdはモジュラー設計とOSの互換性を目的としていますが、SysVinitでは不可能です。

問題 39.2
SysVinitを使用する場合、システムをシャットダウンして電源を切ることに対応するランレベルはどれですか？

A. 0
B. 1
C. 2
D. 3
E. 5

問題 39.3
SysVinitを使用する場合、シングル ユーザー モードに対応するランレベルはどれですか？

A. 0
B. 1
C. 3
D. 5
E. 6

問題 39.4
SysVinitを使用する場合、通常のグラフィック モードに対応するランレベルはどれですか？

A. 0
B. 1
C. 2
D. 3
E. 5
F. 6

問題 39.5
システムの実行中にnfsを有効にするコマンドはどれですか？

A. sudo systemctl status nfs
B. sudo systemctl enable nfs
C. sudo systemctl stop nfs
D. sudo systemctl start nfs

問題 39.6
システムの起動時にnfsを有効にするコマンドはどれですか？

A. sudo systemctl status nfs
B. sudo systemctl enable nfs
C. sudo systemctl stop nfs
D. sudo systemctl start nfs

