いつの間にか夏至も過ぎ、そろそろ今年も半分が終る時期になってしまいました。家の回りの水田も、青々とした若苗が風にそよいでいます。例年なら田植えが終って一段落の時期なものの、今年は水番が当たっているので、朝夕、田んぼの水位の確認・調整に忙しい日々を送っています。
さて、去る6月13日に、ここしばらくの回で紹介してきたPlamo Linux 7.0を公式にリリースしました。DVDイメージはrepository.plamolinux.org から入手できます。サイズの関係でDVDは2枚組みとなったものの、2枚目はTeX回りと動作に必須ではないcontrib的なパッケージを収めているだけなので、TeX(tetex)が不要な方は1枚目のDVDイメージのみでインストールできます。
Plamo Linuxは大手ディストリビューションのような完成度はありませんが、小規模な分、全体の見通しはよく、Linuxの勉強をしたい人や、手作りで自分の環境を作りあげたい人には便利なディストリビューションだと思っています。本連載等でPlamo Linuxに興味を関心を持たれた方は、ぜひ試してみてください。
閑話休題、今回は、文字コードの変更と共にPlamo-7.0で加えた大きな変更点である起動処理回りを解説します。
Plamo-7.0の起動処理
Plamo-7.0でも、Plamo-6.x同様、システムの起動にはsysvinit パッケージを使っています。sysvinitは"SystemV Init "の略で、「 UNIX SystemV(アルファベットのVではなく、ローマ数字の5)が採用した起動処理」の機能を実装したソフトウェアを意味します。
少し昔話をすると、UNIXにはAT&Tベル研究所で開発されたバージョンと、それを元にカリフォルニア大学バークレー校で開発されたバージョンの2種があり、前者の系統をその最終バージョン名を冠して"SystemV (システム・ファイブ、略してSysV)"、後者を"BSD (Berkeley Software Distribution)"と呼び慣わしています。
"SystemV Init"は前者の系統のUNIXが採用したシステムの初期化メカニズムで、複数の「ランレベル (動作モード) 」を用意しているのが特徴です。
ここで言う「ランレベル」とは、全ての機能を使える「通常モード」 、rootユーザのみがログインできるトラブルやメンテナンス時に便利な「シングルユーザモード」 、root以外のユーザもログインできるもののNFS等ネットワーク機能は使えない「ネットワーク無しモード」など、起動するサービスを取捨選択して状況に応じた環境を提供する機能です。
この機能を使えば、何らかのハードウェアトラブルが生じた場合、「 通常モード」から「シングルユーザモード」に切り替えて一般ユーザを追い出し、root権限でバックアップやシステムリカバリ作業を行う、といった操作ができます。
一方、BSD系のUNIXでは「ランレベル」という概念は採用せず、必要なサービスは/etc/rc ファイルで直接起動する、というスタイルになっていました。
複数のランレベルを切り替えられるSysV形式の起動処理は高機能なものの、使用するソフトウェアがその形式に対応している必要があるのに対し、BSD形式では起動したいサービスを/etc/rcファイルに記述するだけで済むので、80年代後半にフリーソフトウェアをインストールしながらUNIXを学んだ人間にとってはBSD形式の方が使いなれた仕組みでした。Slackware Linuxの原作者Patrick Vorkerdingさんも同じように考えて、sysvinitを使いながらもBSD UNIXのrcファイルをエミュレートするスタイルにしたのでしょう。
一方、Linuxがディストリビューションとして進化するにつれ、システムの中身にあまり詳しくないユーザでもさまざまなソフトウェアを簡単にインストール/アンインストールできるようにする必要が生じました。その結果、rcファイルを修正しなければならないBSD形式は敬遠されるようになり、パッケージごとに起動/終了スクリプトをあらかじめ用意するSysV形式が主流になりました。そこで遅ればせながら、Plamo LinuxでもPlamo-7で起動スタイルを正式なSysV形式に変更することにしたわけです。
init回りはその後も進化を続け、UpstartやInitNG、OpenRCなどの仕組みが提案され、最近ではsystemdが主流となってきています。将来的にPlamo Linuxもsystemdに移行するかも知れませんが、それはだいぶ先のことでしょう(苦笑) 。
SysV形式の設定ファイル
UNIX/Linuxの場合、カーネルは、起動後必要な初期化処理等を終えると/sbin/init というコマンドを実行することになっています。
SysV形式の場合、この/sbin/initは/etc/inittab という設定ファイルに従って動作します。そこで、Plamo-7と6.xの/etc/inittab を比較してみましょう。まず、これがPlamo-6.xの/etc/inittab(の主要部分)です。
リスト1 Plamo-6.xの/etc/inittab
11 # Default runlevel.
12 id:3:initdefault:
13
14 # System initialization (runs when system boots).
15 si:S:sysinit:/etc/rc.d/rc.S
16
17 # Script to run when going single user (runlevel 1).
18 su:1S:wait:/etc/rc.d/rc.K
19
20 # Script to run when going multi user.
21 rc:2345:wait:/etc/rc.d/rc.M
22
同じ部分は、Plamo-7.0ではこうなっています。
リスト2 Plamo-7.0の/etc/inittab
4 id:3:initdefault:
5
6 si::sysinit:/etc/rc.d/init.d/rc S
7
8 l0:0:wait:/etc/rc.d/init.d/rc 0
9 l1:S1:wait:/etc/rc.d/init.d/rc 1
10 l2:2:wait:/etc/rc.d/init.d/rc 2
11 l3:3:wait:/etc/rc.d/init.d/rc 3
12 l4:4:wait:/etc/rc.d/init.d/rc 4
13 l5:5:wait:/etc/rc.d/init.d/rc 5
14 l6:6:wait:/etc/rc.d/init.d/rc 6
/etc/inittabは1行が1つの設定で、それぞれ "識別子:ランレベル:アクション:実行コマンド"という形になっています。「 識別子 」はそれぞれの行を区別する任意の文字列、「 ランレベル 」はその行を実行するランレベルの指定(複数可) 、「 アクション 」はプロセスを起動/終了させる際の動作、「 実行コマンド 」はその行が実行するコマンド、を意味します。
「アクション」で"initdefault "を指定すると、その行で指定したランレベルが「デフォルト・ランレベル 」 、すなわち「通常モード」になます。リスト1でも2でも "id:3:initdefault:" なので、デフォルト・ランレベルは"3"です。
"sysinit "を指定すると、その行は起動時に実行されることになります。そのためPlamo-6.xでは15行目で"/etc/rc.d/rc.S "が、Plamo-7.0では6行目で"/etc/rc.d/init.d/rc S "が、システムの起動時に実行されます。"sysinit"で指定した処理が終わればシステムはデフォルト・ランレベルに移行し、Plamo-6.xでは21行目の/etc/rc.d/rc.M 、7.0では11行目の/etc/rc.d/init.d/rc 3 が実行されます。
Plamo-6.xではランレベルを細かく分けず「シングルユーザモード (18行目) 」と「マルチユーザモード (21行目) 」を提供しているだけなのに対し、Plamo-7.0では0から6までのランレベル (8行目から14行目)を設けています。Plamo-7.0のランレベルの割り当ては以下の通りです。
ランレベル
動作モード
0
終了(halt)
1
シングルユーザモード
2
ネットワーク機能なしのマルチユーザモード
3
全ての機能が使えるマルチユーザモード
4
予備
5
GUIログイン用
6
リブート
これはLFS(Linux From Scratch)の設定をそのまま引きついでおり、LFSはLSB(Linux Standard Base)の仕様を元にしているので、SysV形式を使っているディストリビューションの標準的な割り当てです。
リスト1と2を見比べると、Plamo-6.xでは処理にrc.Sとrc.M、rc.Kの3つのスクリプトを使いわけているのに対し、Plamo-7.0ではrcという一つのスクリプトが与える引数によって動作を変えていることがわかります。さて、それではどのようにrcスクリプトはランレベルごとに指定された任意の数のサービスを起動するのでしょう?
ランレベルごとのサービス起動
その答は/etc/rc.d/以下にあるrc0.dからrc6.dの各ディレクトリ にあります。
$ ls /etc/rc.d/
init.d/ rc.initpkg* rc0.d/ rc1.d/ rc2.d/ rc3.d/ rc4.d/ rc5.d/ rc6.d/ rcS.d/
このrc0.dからrc6.dの各ディレクトリがランレベルごとのサービス起動用スクリプトの置き場になっており、ランレベルに応じてrcスクリプトがそれらを順に実行していくわけです。
サービス起動用スクリプトは本体を/etc/rc.d/init.d/ 以下に置き、起動したいランレベルへは"S"か"K"を先頭につけた「2ケタの数字」+「スクリプト名」という形のシンボリックリンク を置きます。
$ ls -l /etc/rc.d/rc5.d/
合計 126,976
lrwxrwxrwx 1 root root 18 6月 6日 14:41 S19iptables -> ../init.d/iptables*
lrwxrwxrwx 1 root root 17 6月 6日 14:38 S20network -> ../init.d/network*
lrwxrwxrwx 1 root root 24 6月 7日 19:55 S20vboxdrv -> /etc/rc.d/init.d/vboxdrv*
lrwxrwxrwx 1 root root 17 6月 6日 14:49 S21unbound -> ../init.d/unbound
....
rcスクリプトは、指定されたランレベルに応じて、rc0.dからrc6.dディレクトリ内にある"S"で始まるスクリプトを、2ケタの数字の順に実行し、必要なサービスを起動していきます。サービスの起動順は2ケタの数字を適切に割り振ることで制御できるので、サービス間の依存性にも対応しています。
"S"ではなく"K"で始まるシンボリックリンクもあります。たとえば、rc1.d/以下ではほとんどのリンクが"K"で始まっています。
$ ls -l /etc/rc.d/rc1.d/
合計 139,264
lrwxrwxrwx 1 root root 14 6月 6日 14:49 K00cups -> ../init.d/cups*
lrwxrwxrwx 1 root root 17 6月 6日 14:45 K05lightdm -> ../init.d/lightdm*
lrwxrwxrwx 1 root root 15 6月 6日 14:36 K08crond -> ../init.d/crond*
lrwxrwxrwx 1 root root 13 6月 6日 14:41 K10gpm -> ../init.d/gpm
....
これら"K"で始まるリンクはランレベルの切り替え時に使用され、「 そのランレベルに入った際に終了するサービス」を意味します。
上記で示したrc1.d/はランレベル1、すなわち「シングルユーザモード」用のランレベルで、このランレベルに入ると起動していたほとんどのサービスは終了し、必要最小限の機能のみに切り替わるわけです。
一方、Plamo-6.xまでは/etc/rc.d/rc.Sで行なっていたファイルシステムのマウントやシステムクロック、スワップの設定など、ユーザ領域で必要な初期化処理もそれぞれ独立したスクリプトとして、/etc/rc.d/rcS.d/に置いたシンボリックリンクから実行するようになりました。
$ ls -l /etc/rc.d/rcS.d/
合計 61,440
lrwxrwxrwx 1 root root 21 6月 6日 14:38 S00mountvirtfs -> ../init.d/mountvirtfs*
lrwxrwxrwx 1 root root 17 6月 6日 14:38 S05modules -> ../init.d/modules*
lrwxrwxrwx 1 root root 18 6月 6日 14:38 S08localnet -> ../init.d/localnet*
lrwxrwxrwx 1 root root 15 6月 6日 14:38 S10eudev -> ../init.d/eudev*
...
mountvirtfs はtmpfsやdevfs,sysfsといった仮想ファイルシステムのマウント、modules はあらかじめ指定しておいたモジュールのロード、localnet はloopbackインターフェイスの設定、eudev は周辺機器を動的に認識するudevデーモンの起動、を意味し、従来はrc.Sで一気にやっていた処理を、1つ1つのコマンドごとに分割して、rcS.d/以下のシンボリックリンクから実行するように変更しています。
rcスクリプトはシンボリックリンクを辿って/etc/rc.d/init.d/以下のコマンドを実行するだけなので、起動スクリプトの実行パーミッションを落せば、シンボリックリンクが張ってあってもそのサービスは起動されなくなります。
Plamo Linuxでは、不要なサービスはできるだけ起動しない、という方針で、httpdやsamba、dovecotなど、パッケージをインストールしても、そのままでは起動しないサービスがいくつかあります。これらは起動スクリプトの実行パーミッションを落としているので、サービスを起動したい場合はchmod +xで実行可能にしてください。
ちなみにrcスクリプトは起動する各コマンドの終了状況をチェックし、起動の成功("OK") 、失敗("FAIL")を色分けして表示してくれます。下図はPlamo-7.0の起動画面で、黄色で"WARN"になっているのが、実行パーミッションが無いため起動されなかったサービスです。
図1 各種サービスの起動状況
なお、SysV形式を採用しているディストリビューションの多くでは、chkconfigやsysv-rc-confと呼ばれるランレベル設定用のツールが用意されていますが、Plamo Linuxでは今のところ、これらのツールは採用していません。
このようにSysV形式の起動処理は、sysvinitパッケージだけではなく、インストールするソフトウェアそれぞれについて起動/終了用スクリプトを用意すると共に、それらを適切な順番で起動するように設定したシンボリックリンクを用意するなど、システム全体に渡る調整が必要になります。
一方、SysV形式が提供する「ランレベル」は面白い概念ではあるものの、一人が一台のLinux環境を専有する時代においては、それほど必要な機能ではありません。
そのような事情から、Plamo Linuxでは長くrc.S/rc.M/rc.localのスタイルを使い続けてきたものの、Plamo-7.0では全パッケージを更新する予定だったので、この機会に、と、正式なSysV形式の起動処理を採用することにした次第です。
Plamo Linuxの場合、開発者リソースが少ないこともあって、「 あれば便利」な機能を積極的に採用するよりも、「 そろそろ不便」になってきたから仕方なく移行することが多くなりがちで、前回紹介した文字コードや今回取りあげたSysV形式の起動システムなど、その典型例と言えるでしょう。もう少し新技術にも積極的にならないといけないなぁ、、と思うものの、古い皮袋は新しい葡萄酒に馴染みにくいようです(苦笑) 。