次のページ 前のページ 目次へ

4. ルートファイルシステムの作成

ルートファイルシステムを作る際には,システムを実行するために必要なファ イルを選択する必要があります.この章では, 圧縮形式のルートファイルシステムの作り方を説明します. あまり行われませんが、直接ルートファイルシステムとしてマウントされる, 圧縮形式でないファイルシステムをフロッピー上に作る方法もあります.この 方法は 非 RAM ディスクのルートファイルシステム の章で説明します.

4.1 概要

root ファイルシステムには,完全に動作する Linux システムに必要なファイ ル全てが入っていなければなりません.そのためディスクには Linux システ ムにとって必要最小限のファイルが入っていなければなりません:

もちろん何かがその上で動かなければシステムは役に立ちません.以下のよう なことができなければ,ルートディスクは役に立つとは言えません:

ここで圧縮形式のファイルシステムの作り方を説明します.このファイ ルシステムはディスク上では圧縮されていて,起動時に RAM ディスク上に展 開されます. 圧縮形式のファイルシステムを使うと,標準の 1.44M のフロッピーにたくさ んのファイル(約 6 メガバイト)を入れることができます.このファイルシステム はフロッピーよりもずっと大きいため,フロッピー上で作ることはできません. したがって,他の場所で作成して圧縮をしてからフロッピーに書き込まなけれ ばなりません.

4.2 ファイルシステムの作成

このようなルートファイルシステムを作成するには,圧縮前のファイル全てを 格納できる大きさを持つデバイスが必要になります.およそ 4 メガバイト程 度の容量を持つデバイスが必要になるでしょう.いくつかの候補を以下に挙げ ます:

以上のどれかを用いてデバイスを作ったら,まず次のようなコマンドを実行し ます.

        dd if=/dev/zero of=DEVICE bs=1k count=3000

このコマンドによってデバイスの中身が 0 で埋め尽くされます.圧縮ファイ ルシステムを作成するにあたってはこの作業は重要です.未使用の部分を全て 0 にしておくと圧縮率を最大にできるからです.

次にファイルシステムを作成します. RAM ディスクに自動コピーされるルートディ スクとして Linux カーネルが認識できるファイルシステムには, minix と ext2 があります.ext2 の方がお勧めです.ext2 を使っている場合は -i オプションを指定してデフォルトより多くの i-ノードを作って おくとよいでしょう. -i 2000 としておけば i-ノードを使い切る心配 はしなくてよいでしょう.あるいは /dev から不必要なファイルを消 して i-ノードを節約してもいいでしょう.デフォルトでは mke2fs は 1.44 メガのフロッピーに 360 個の i-ノードを作ります.さっき筆者のレスキュー ディスクを見てみたら 120 個の i-ノードが余っていました.しかし /dev ディレクトリのファイルを全て含めると 360 個を簡単に越え てしまうでしょう.圧縮形式のルートファイルシステムを用いるとファイルシ ステムの大きさが増えますから,デフォルトの i-ノードの数も 360 以上にな ります.しかしそれでもファイルを減らすか i-ノードを増やすかする必要が あるでしょう.

i-ノードを増やすには,次のようなコマンドを使います:

        mke2fs -m 0 -i 2000 DEVICE

(ループバックデバイスを使うときは,上記の DEVICE の部分を使用するファ イルに置き換えてください.この場合,mke2fs は実行の確認をしてくると 思います.)

mke2fs コマンドは利用可能な容量を自動的に検知し,ファイルシステム を適切に設定してくれます.-m 0 パラメータを利用するとスーパー ユーザ専用の予約領域を作らなくなるので,利用できるディスク領域が増えま す.

次にデバイスをマウントします:

        mount -t ext2 DEVICE /mnt

(まだ作っていなければ,マウントポイント /mnt を用意しなければ なりません.)以降の章では,対象となるディレクトリ名は /mntか らの相対パスで表すものとします.

4.3 ファイルシステムの移植

ルートファイルシステム用の現実的な最小のディレクトリ構成は以下のように なります:

(ここで示したディレクトリ構造はルートフロッピー用のものです.実際の Linux システムではもっと複雑ですし,ちゃんとした方針に従っています.こ の方針は Filesystem Hierarchy Standard と呼ばれるもので,ファイルを置 くべき場所を決める規則です.)

このディレクトリのうち 3 つは 空ディレクトリなので,単にmkdirコマンドで作成するだけでかまいませ ん./procディレクトリは proc ファイルシステムを配置するための 単なる器です./mnt/usrは,ブート/ルートシステムが 起動した後に使うただのマウントポイントです.というわけで,繰り返しにな りますが,この 3 つのディレクトリは作成するだけでかまいません.

残りの 4 つのディレクトリについては以降の章で説明します.

/dev

/dev ディレクトリは全ての Linux システムに必須のディレクトリ で,システムが使う全てのデバイスに対するスペシャルファイルがここにあり ます./dev 自身は普通のディレクトリで,ごく普通に mkdir コマンドで作成できます.しかしデバイスのスペシャルファイルは特別な方法 (mknodコマンド)を用いて作成しなければなりません.

もっと楽な方法もあります.既に存在する /dev ディレクトリの内 容をコピーして,それから不要なものを消去するのです.注意しなければいけ ない点は,デバイスのスペシャルファイルをコピーする場合には -R オ プションが必要なことくらいです.-R オプションを指定すると,ファイ ルの内容はコピーせずにディレクトリがコピーされます.R は必ず大文字 にします.小文字の -r オプションを使うと全く異なった動作とな ります.ハードディスクの内容が(少なくともフロッピーが一杯になるまで)全 部コピーされてしまうのです! ですから次のコマンドを使うときはオプション に注意してください:

        cp -dpR /dev /mnt

ここでフロッピーは /mnt にマウントされているものとします. d オプションはシンボリックリンクをコピーする際に,リンク先の実体 ではなくリンクそのものをコピーするための指定です. p オプションは 元のファイルの属性を保存します(したがって所有者情報も保存されます).

あえて手間のかかる方法でやりたい場合は, コピーしたいデバイスのメジャー 番号とマイナー番号を ls -l で調べ, mknod コマンドでフロッ ピー上にそれらを作成します.

デバイスをコピーしたあと,必要なデバイスが全部ちゃんとレスキューディス クにあるかどうかを確認しましょう.例えば,ftape はテー プデバイスを使いますから,ブートディスクからテープデバイスにアクセスす る予定があるなら,テープのデバイスファイルは全てコピーしておく必要 があります.

それぞれのデバイスファイルにひとつづつ i-ノードが必要です.フロッ ピーのファイルシステムでは i-ノードは不足しがちですから,必要でないデ バイスファイルをフロッピーの /devディレクトリから消しておくと 良いでしょう.明らかに不必要なデバイスが結構あるはずです.例えば SCSI ディスクを持っていないのなら sd ではじまる名前のファイルは全て消 してしまえます.同様にシリアルポートを使わないつもりなら cuaで始 まるファイルも消せます.

次のファイルはこのディレクトリに必ずなければなりません: console, kmem, mem, null, ram, tty1

/etc

このディレクトリには多くの設定ファイルが置かれます.大抵のシステムでは 設定ファイルは以下の 3 つに分類できます:

  1. 絶対に必要なもの.例えば rc, fstab, passwd など.
  2. 必要かもしれないけれど,よくわからないもの.
  3. 勝手にできてしまうゴミ.

必要でないファイルは以下のコマンドで見つけることができます:

        ls -ltru

このコマンドを使うと,ファイルは最後にアクセスされた日が古い順に一覧表 示されるので,アクセスされていないファイルがあれば,ルートフロッピーから 取り除いてしまいましょう.

私の場合ルートフロッピーに入れる設定ファイルの数は下記の 15 個にまで減 らしています.これにより,以下の 3 種類のファイルを扱えばよいようになっ ています:

  1. ブート/ルートシステムに設定しなければならないファイル:
    1. rc.d/* -- システムの起動と実行レベル変更のスクリプト
    2. fstab -- マウントするファイルシステムのリスト
    3. inittab -- init プロセス (起動時の最初のプロセス)のパラメータ.
  2. ブート/ルートシステム用に短くしておいた方が良いファイル:
    1. passwd -- ユーザ,ホームディレクトリのリスト
    2. group -- ユーザグループ
    3. shadow -- ユーザのパスワード.このファイルは無いかもしれない.
    4. termcap -- 端末機能データベース
    セキュリティが重要な場合は,passwdshadow を整理して, システムの外にユーザのパスワードがコピーされないようにすべきです. またこうすれば,フロッピーからブートしたとき,予定外のログインを 拒否できます. passwd には少なくともrootユーザを入れてください. 他にログインさせるつもりのユーザがいるなら,ホームディレクトリやシェル も確認しましょう. termcap (端末データベース) のサイズは,通常数百キロバイト程度です. 起動ディスクやルートディスクに入れる termcap ファイルには,使用す る端末の項目だけを入れるようにしましょう.普通は linux-console の 項目だけになります.
  3. 残り.現時点でこれらのファイルを置いたままでシステムはちゃんと働 いているので,そのままにしてあります.

この中で本当に設定しなければならないのは 2 個のファイルだけです.その 中身は驚くほど小さいものです.

inittabsysinit 行は変更して, rc 等の基本的となる起動スクリプトを実行するようにしておかな ければなりません.シリアルポートからのログインを禁止するならば, inittab に含まれる getty のエントリのうち,行末が ttys ま たは ttyS デバイスになっているものを全部コメントアウトします. コンソールからはログインできるようにtty のエントリは残しておきま しょう.

最小限の inittab は次のようになるでしょう:

        id:2:initdefault:
        si::sysinit:/etc/rc
        1:2345:respawn:/sbin/getty 9600 tty1
        2:23:respawn:/sbin/getty 9600 tty2

inittab ファイルは,起動時やマルチユーザモードへの移行時, 電源断のときなどにシステムが起動(あるいは再起動)するものを定義します. ここで特に注意しておきたい点は, inittab に記述されているファイル名 を注意深く確認することです.記述されているプログラムを init が見 つけられないと,起動ディスクはハングします.このような場合にはエラーメッ セージさえ表示されないかもしれません.

プログラムによっては,他の場所には移動させられないこともあります. 他のプログラムに位置がハードコード (直接記述) されている場合などが これにあたります. /etc/reboot の場所は /etc/shutdown でハード コードされています.もし reboot を /bin/reboot に移動させると, shutdownreboot ファイルを 見つけられないので,実行できなくなってしまいます.

残りのファイルについては /etc ディレクトリにある全てのテキストファイル を単にフロッピーにコピーするだけです.加えて /etc ディレクトリにある実 行ファイルのうち,不要だという自信の無いものを全てコピーします. ルートディスクのサンプルのディレクトリ一覧 の章が役に立つでしょう.このようなファイルをコピーするだけでうまく行く こともありますが,システムはそれぞれ大きく異なるのが普通ですから,当然 うまく行かない場合もありえます.絶対確実と言える方法は,inittab からたどって必要なファイルを全部確認することだけです.

現在ほとんどのシステムでは,実行レベルごとに異なるシェルスクリプトの置 き場所として /etc/rc.d ディレクトリを使っています.とにか く小さくしたい場合には rc スクリプトひとつだけにすることもできま すが,実際には今のシステムから inittab と /etc/rc.d ディレクトリをコピーして,フロッピーベースのシ ステムに不要なものを削っていく方がずっと簡単でしょう.

/bin と /sbin

/bin ディレクトリには lsmv, cat, dd などの基本的な操作を行うときに必要なコマンドを置いておくと良いでしょう. 付録の ルートディスクのサンプルのディレクトリ一覧 で,/bin ディレクトリや /sbinディレクトリに置いたファ イルの例を見てください.この例では cpio, tar, gzip といっ たバックアップの復元に必要なプログラムはありません.これはブート/ルー トフロッピーの空き領域を増やすために,別のフロッピー(ユーティリティディ スク)に入れてあるからです.いったんブート/ルートフロッピーを使ってブー トすると,このフロッピーの内容は自動的に RAM ディスクにコピーされます. すると,フロッピーディスクドライブは空いて他のディスクをマウントできる ようになるので,ユーティリティディスクをマウントして使います.筆者はユー ティリティディスクを普通 /usr にマウントしています.

ユーティリティフロッピーの作成方法は後述の ユーティリティディスクの作成の節で説明し ています.バックアップの作成に使ったのと同じバージョンのバックアップユー ティリティを保存しておく方がたぶんよいでしょう.そうすればバックアップ テープを読めないバージョンのものをインストールして時間を無駄にすること もないでしょう.

次のプログラムは確実に入れましょう: init, getty(ま たは同等品), login, mount, rc スクリプトを実行できるシェル, sh からそのシェルへのリンク.

/lib

/lib には必要な共有ライブラリとローダを置きます.必要な共有ラ イブラリが /lib になければシステムをブートすることができません.運が良 ければエラーメッセージで何が足りないかがわかるでしょうが.

ほとんど全てのプログラムは,少なくとも libc ライブラリである libc.so.N を必要とします.ここで,N は現在のバージョ ン番号です.読者のみなさんの /lib をチェックしてみてください. libc.so.N は通常,完全なバージョン番号を持つファイルへのシンボリッ クリンクです:

% ls -l /lib/libc*
-rwxr-xr-x   1 root     root      4016683 Apr 16 18:48 libc-2.1.1.so*
lrwxrwxrwx   1 root     root           13 Apr 10 12:25 libc.so.6 -> libc-2.1.1.so*

この場合には libc-2.1.1.so が必要となります.コピーすべき他のラ イブラリを見つけるには,入れようとするバイナリを全て調べ, ldd コマンドを使って依存関係をチェックします.例を示し ます:

        % ldd /sbin/mke2fs
        libext2fs.so.2 => /lib/libext2fs.so.2 (0x40014000)
        libcom_err.so.2 => /lib/libcom_err.so.2 (0x40026000)
        libuuid.so.1 => /lib/libuuid.so.1 (0x40028000)
        libc.so.6 => /lib/libc.so.6 (0x4002c000)
        /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

右側にあるファイルが必要なものです.ファイルはシンボリックリンクである こともあります.

一部のライブラリは非常に大きく,容易にはルートファイルシステ ムに入れられないこともあります.例えば,先に挙げた libc.so のサイ ズは約 4 メガバイトです.このファイルをルートファイルシステムにコピー する際には,ライブラリを strip する必要があるかもしれません.この手順 については, ファイルシステムのサイズの削減 の節を参照してください.

/lib にはライブラリをロードするためのローダも入れる必要があり ます.ローダのファイルの名前は ld.so (a.out ライブラリ用) または ld-linux.so (ELF ライブラリ用) です. 新しいバージョンの ldd を使えば,(先に示した例のように)どのローダ が必要なのかが正確に分かりますが,古いバージョンの ldd ではこれが 分からないことがあります.どちらが必要なのかが確かでなければ,ライブラ リに対して file コマンドを実行してください.実行例を示します:

        % file/lib/libc.so.4.7.2 /lib/libc.so.5.4.33 /lib/libc-2.1.1.so
        /lib/libc.so.4.7.2: Linux/i386 demand-paged executable (QMAGIC), stripped
        /lib/libc.so.5.4.33: ELF 32-bit LSB shared object, Intel 80386, version 1, stripped
        /lib/libc-2.1.1.so: ELF 32-bit LSB shared object, Intel 80386, version 1, not stripped

QMAGIC4.7.2 は a.out 用ライブラリであることを示し, ELF5.4.332.1.1 が ELF 用ライブラリであることを 示します.

作ろうとしているルートファイルシステムに必要なローダをコピーしてくださ い.両方とも必要な場合もあるかもしれません.入れるバイナリに対して,ラ イブラリとローダは慎重にチェックしなければなりません.カーネルが 必要なライブラリをロードできない場合,普通カーネルはエラーメッセージも 出さずに止まってしまうでしょう.

4.4 PAM と NSS の設定

ldd では見えない,動的にロードされるライブラリがシステム に必要とされるかもしれません.

PAM (差し替え可能な認証モジュール)

システムが PAM (差し替え可能な認証モジュール)を使っている場合,ブート ディスクにいくらか手を加えないとログインできなくなってしまいます.PAM とはユーザの認証とサービスへのユーザアクセスとを制御するための手法で, きれいにモジュール化されているものです.システムが PAM を使っているか どうかを簡単に調べるには,ハードディスクの /etc ディレク トリに pam.conf ファイルか pam.d ディレクト リがあるかどうか確認することです.このどちらかが存在する場合,最低限の PAM サポートを準備しなければなりません.(調べるための別の方法としては, ldd を login の実行ファイルに対して使ってみ る方法もあります.出力に libpam.so が含まれる場合には, PAM が必要です.)

好運なことに,ブートディスクでは通常,セキュリティを考える必要は全くあ りません.なぜなら,マシンに物理的にアクセスできるならば,いずれにせよ どんなことでもできるからです.よって,事実上は PAM を無効化しても構い ません.これは次のような内容の簡単な /etc/pam.conf を 作成するだけで OK です:


OTHER   auth       optional     /lib/security/pam_permit.so
OTHER   account    optional     /lib/security/pam_permit.so
OTHER   password   optional     /lib/security/pam_permit.so
OTHER   session    optional     /lib/security/pam_permit.so

/lib/security/pam_permit.so ファイルも ルートファイルシステムにコピーします.このライブラリは 8K 程度しかないので,負担は最小限で済みます.

この設定にすると,そのマシンのファイルやサービスには誰でも完全なアクセ スができるようになります.何らかの理由でブートディスクでもセキュリティ に注意したい場合には,ハードディスクの PAM の設定の一部あるいは全部を ルートファイルシステム上にコピーしなければなりません.PAM の文書をよく 読んで,/lib/security にあるライブラリのうち必要なものを ルートファイルシステムにコピーしてください.

また,ブートディスクには /lib/libpam.so を入れる必要があ りますが,既に読者のみなさんはこれは知っているはずです.なぜなら, /bin/login に ldd を実行したときに,このファイルが依存関 係で表示されたからです.

NSS (ネームサービス切り替え)

glibc(別名 libc6)を使っている場合,ネームサービスに手を加えなければロ グインできません.NSS ではファイル /etc/nsswitch.conf を 使って様々なサービスへのデータベース参照を制御します.ネットワークのサー ビス(DNS や NIS の参照等)にアクセスするつもりがなければ,以下のような 簡単な nsswitch.conf を準備するだけです:


     passwd:     files 
     shadow:     files 
     group:      files 
     hosts:      files
     services:   files
     networks:   files
     protocols:  files
     rpc:        files
     ethers:     files
     netmasks:   files     
     bootparams: files
     automount:  files 
     aliases:    files
     netgroup:   files
     publickey:  files

この指定では全てのサービスをローカルファイルだけから受けるようになりま す.また,/lib/libnss_files.so.1 ファイルも必要になる でしょう.このファイルはファイルの参照を扱うために動的にロードされます.

ブートディスクからネットワークにアクセスすることを考えているならば,もっ とちゃんとした nsswitch.conf を書こうと思うかもしれません. 指定しようとするサービスごとに /lib/libnss_サービス.so.1を組み込む 必要があることを忘れないでください.

4.5 モジュール

モジュール化したカーネルを使っている場合,起動後にブートディスクからど のモジュールをロードしたいのかを考えなければなりません.バックアップテー プがフロッピーテープにある場合はftape モジュールや zftapeモ ジュールが必要でしょうし,SCSI 機器があるなら SCSI デバイス用のモジュー ルが必要でしょう.また,緊急時にネットにアクセスしたければ PPP や SLIP をサポートするためのモジュールも必要になるでしょう.

このようなモジュールは /lib/modules に置きます.また, insmod, rmmod, lsmod も入れなければなりません.モジュー ルを自動的にロードするかどうかによって,modprobe, depmod, swapout が必要になるかどうかも決まります.kerneld を使うなら ば /etc/conf.modules も一緒に入れましょう.

しかし,モジュールを使う最大の利点は,必須でないモジュールをユーティリ ティディスクに移しておいて必要な時にロードできる点です.これにより,ルー トディスクで使う容量が減ります.異なる種類のデバイスを多く扱わなければ ならないかもしれない場合,たくさんのドライバを組み込んだ巨大なカーネル を1つ作るよりもこのアプローチの方が好ましいでしょう.

圧縮形式の ext2 ファイルシステムを使う時には RAM ディスクと ext2 のサポートはカーネルに組み込まなければなりません.これらをモジュール として使うことはできません.

4.6 その他の細かい事項

/var/run/utmp ファイルや /var/log ディレクト リが存在しない場合,一部のシステムプログラム(login 等)は文句を言っ てきます.そこで次のようにしておきます:

        mkdir -p /mnt/var/{log,run}
        touch /mnt/var/run/utmp

必要なライブラリを設定したら,最後に ldconfig を実行してルートファ イルシステムの /etc/ld.so.cache を作り直します.このキャッ シュがローダにライブラリの場所を教えます.ld.so.cache を作り直す には次のコマンドを実行します:

        chdir /mnt; chroot /mnt /sbin/ldconfig

chroot が必要なのは,ldconfig が常にルートファイルシステムの キャッシュを作り直すからです.

4.7 仕上げ

ルートファイルシステムの作成が終わったら,このファイルシステムをアンマ ウントし,ファイルにコピーして,圧縮します:

        umount /mnt
        dd if=DEVICE bs=1k | gzip -v9 > rootfs.gz

これが終わったら圧縮形式のルートファイルシステムである rootfs.gz ができるはずです.この大きさを調べ,フロッピーに収まることを確かめましょ う.収まり切らない場合には,ファイルをいくつか消しましょう. ルートファイルシステムのサイズを小さくする場合, ルートファイルシステムのサイズの削減セクショ ンが参考になるでしょう.


次のページ 前のページ 目次へ