ルートファイルシステムを作る際には,システムを実行するために必要なファ イルを選択する必要があります.この章では, 圧縮形式のルートファイルシステムの作り方を説明します. あまり行われませんが、直接ルートファイルシステムとしてマウントされる, 圧縮形式でないファイルシステムをフロッピー上に作る方法もあります.この 方法は 非 RAM ディスクのルートファイルシステム の章で説明します.
root ファイルシステムには,完全に動作する Linux システムに必要なファイ ル全てが入っていなければなりません.そのためディスクには Linux システ ムにとって必要最小限のファイルが入っていなければなりません:
/dev, /proc, /bin, /etc, /lib, /usr,
/tmp
sh, ls, cp, mv
等rc, inittab, fstab
等/dev/hd*, /dev/tty*, /dev/fd0
等もちろん何かがその上で動かなければシステムは役に立ちません.以下のよう なことができなければ,ルートディスクは役に立つとは言えません:
fsck
を実行する必要があります.
cpio, tar, gzip, ftape
等のアーカイブや圧縮用のユーティリティを用
いて復元する作業.
ここで圧縮形式のファイルシステムの作り方を説明します.このファイ ルシステムはディスク上では圧縮されていて,起動時に RAM ディスク上に展 開されます. 圧縮形式のファイルシステムを使うと,標準の 1.44M のフロッピーにたくさ んのファイル(約 6 メガバイト)を入れることができます.このファイルシステム はフロッピーよりもずっと大きいため,フロッピー上で作ることはできません. したがって,他の場所で作成して圧縮をしてからフロッピーに書き込まなけれ ばなりません.
このようなルートファイルシステムを作成するには,圧縮前のファイル全てを 格納できる大きさを持つデバイスが必要になります.およそ 4 メガバイト程 度の容量を持つデバイスが必要になるでしょう.いくつかの候補を以下に挙げ ます:
RAMDISK_SIZE = nnnこれによって,RAM ディスクに割り当てることができる最大の RAM 容量を指 定します.デフォルト値は 4096K です.たぶんこの大きさで十分でしょう. メモリが 8M より少ないマシンでは,このような設定で RAM ディスクを使う のは避けたほうがよいでしょう. /dev/ram0や/dev/ram, /dev/ramdiskと いったデバイスファイルがあることを確認しましょう.もしなければ,
mknod
を使って /dev/ram0 を作りましょう(メジャー番号
は 1, マイナー番号は 0 です).
man losetup
で調べてください.
losetup
がなければ,
ftp://ftp.win.tue.nl/pub/linux/utils/util-linux/
にある util-linux
パッケージに含まれている,対応版
mount
と unmount
でも同じことができます.
システム上にループバックデバイス(/dev/loop0,
/dev/loop1等)が無ければ,コマンド
``mknod /dev/loop0 b 7 0
'' を実行して作成しましょう.
既に対応版の mount
と umount
のバイナリをインストール済みなら,
十分な大きさを持つハードディスクに一時ファイルを作成します(ここでは
/tmp/fsfile とします).次のようなコマンドを使います:
dd if=/dev/zero of=/tmp/fsfile bs=1k count=nnn
これにより,nnn ブロックのファイルが作成されます.
以下の手順でデバイス名を指定するところでは, DEVICE の代わりにこの作成
したファイルの名前を使ってください. mount をループバックデバイスに対し
て使うには ``-o loop
'' オプションを用います.
以下に例を示します:
mount -o loop -t ext2 /tmp/fsfile /mnt
このようにすればファイル /tmp/fsfile が /mnt
に
(ループバックデバイス経由で)マウントされます. df
コマンドを使っ
て確認してください.
以上のどれかを用いてデバイスを作ったら,まず次のようなコマンドを実行し ます.
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
か
らの相対パスで表すものとします.
ルートファイルシステム用の現実的な最小のディレクトリ構成は以下のように なります:
/dev
-- デバイス,I/O の実行に必要/proc
-- proc ファイルシステムに必要なディレクトリ/etc
-- システム設定ファイル/sbin
-- 必須のシステムバイナリ/bin
-- システムの一部とみなされる基本バイナリ/lib
-- プログラム実行に使う共有ライブラリ/mnt
-- 他のディスクを扱うためのマウントポイント/usr
-- その他のユーティリティやアプリケーション(ここで示したディレクトリ構造はルートフロッピー用のものです.実際の Linux システムではもっと複雑ですし,ちゃんとした方針に従っています.こ の方針は Filesystem Hierarchy Standard と呼ばれるもので,ファイルを置 くべき場所を決める規則です.)
このディレクトリのうち 3 つは
空ディレクトリなので,単にmkdir
コマンドで作成するだけでかまいませ
ん./proc
ディレクトリは proc ファイルシステムを配置するための
単なる器です./mnt
と/usr
は,ブート/ルートシステムが
起動した後に使うただのマウントポイントです.というわけで,繰り返しにな
りますが,この 3 つのディレクトリは作成するだけでかまいません.
残りの 4 つのディレクトリについては以降の章で説明します.
/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
このディレクトリには多くの設定ファイルが置かれます.大抵のシステムでは 設定ファイルは以下の 3 つに分類できます:
rc, fstab, passwd
など.必要でないファイルは以下のコマンドで見つけることができます:
ls -ltru
このコマンドを使うと,ファイルは最後にアクセスされた日が古い順に一覧表 示されるので,アクセスされていないファイルがあれば,ルートフロッピーから 取り除いてしまいましょう.
私の場合ルートフロッピーに入れる設定ファイルの数は下記の 15 個にまで減 らしています.これにより,以下の 3 種類のファイルを扱えばよいようになっ ています:
rc.d/*
-- システムの起動と実行レベル変更のスクリプトfstab
-- マウントするファイルシステムのリストinittab
-- init
プロセス
(起動時の最初のプロセス)のパラメータ.
passwd
-- ユーザ,ホームディレクトリのリストgroup
-- ユーザグループ
shadow
-- ユーザのパスワード.このファイルは無いかもしれない.
termcap
-- 端末機能データベースpasswd
と shadow
を整理して,
システムの外にユーザのパスワードがコピーされないようにすべきです.
またこうすれば,フロッピーからブートしたとき,予定外のログインを
拒否できます.
passwd
には少なくともroot
ユーザを入れてください.
他にログインさせるつもりのユーザがいるなら,ホームディレクトリやシェル
も確認しましょう.
termcap
(端末データベース) のサイズは,通常数百キロバイト程度です.
起動ディスクやルートディスクに入れる termcap
ファイルには,使用す
る端末の項目だけを入れるようにしましょう.普通は linux-console
の
項目だけになります.
この中で本当に設定しなければならないのは 2 個のファイルだけです.その 中身は驚くほど小さいものです.
rc
は以下のようになっています:
#!/bin/sh /bin/mount -av /bin/hostname Kangarooディレクトリが正しいことを必ず確かめてください.
hostname
は特に実行する必要はありません.単に見栄えを良
くするためのものです.
/dev/ram0 / ext2 defaults /dev/fd0 / ext2 defaults /proc /proc proc defaults既に存在する
fstab
のエントリーをコピーしてもかまいませんが,ハー
ドディスクのパーティションが自動的にはマウントされないようにすべきです.
noauto
オプションを使えば,そのような設定にできます.こうしておけ
ば,ハードディスクが壊れた時にもこのブートディスクを使用できます.inittab
の sysinit
行は変更して,
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
に移動させると, shutdown
は reboot
ファイルを
見つけられないので,実行できなくなってしまいます.
残りのファイルについては /etc
ディレクトリにある全てのテキストファイル
を単にフロッピーにコピーするだけです.加えて /etc
ディレクトリにある実
行ファイルのうち,不要だという自信の無いものを全てコピーします.
ルートディスクのサンプルのディレクトリ一覧
の章が役に立つでしょう.このようなファイルをコピーするだけでうまく行く
こともありますが,システムはそれぞれ大きく異なるのが普通ですから,当然
うまく行かない場合もありえます.絶対確実と言える方法は,inittab
からたどって必要なファイルを全部確認することだけです.
現在ほとんどのシステムでは,実行レベルごとに異なるシェルスクリプトの置
き場所として /etc/rc.d ディレクトリを使っています.とにか
く小さくしたい場合には rc
スクリプトひとつだけにすることもできま
すが,実際には今のシステムから inittab
と
/etc/rc.d ディレクトリをコピーして,フロッピーベースのシ
ステムに不要なものを削っていく方がずっと簡単でしょう.
/bin
ディレクトリには ls
や mv
, cat
, dd
などの基本的な操作を行うときに必要なコマンドを置いておくと良いでしょう.
付録の
ルートディスクのサンプルのディレクトリ一覧
で,/bin
ディレクトリや /sbin
ディレクトリに置いたファ
イルの例を見てください.この例では cpio
, tar
, gzip
といっ
たバックアップの復元に必要なプログラムはありません.これはブート/ルー
トフロッピーの空き領域を増やすために,別のフロッピー(ユーティリティディ
スク)に入れてあるからです.いったんブート/ルートフロッピーを使ってブー
トすると,このフロッピーの内容は自動的に RAM ディスクにコピーされます.
すると,フロッピーディスクドライブは空いて他のディスクをマウントできる
ようになるので,ユーティリティディスクをマウントして使います.筆者はユー
ティリティディスクを普通 /usr
にマウントしています.
ユーティリティフロッピーの作成方法は後述の ユーティリティディスクの作成の節で説明し ています.バックアップの作成に使ったのと同じバージョンのバックアップユー ティリティを保存しておく方がたぶんよいでしょう.そうすればバックアップ テープを読めないバージョンのものをインストールして時間を無駄にすること もないでしょう.
次のプログラムは確実に入れましょう: init
, getty
(ま
たは同等品), login
, mount
, rc スクリプトを実行できるシェル,
sh
からそのシェルへのリンク.
/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
QMAGIC
は 4.7.2
は a.out 用ライブラリであることを示し,
ELF
は 5.4.33
と 2.1.1
が ELF 用ライブラリであることを
示します.
作ろうとしているルートファイルシステムに必要なローダをコピーしてくださ い.両方とも必要な場合もあるかもしれません.入れるバイナリに対して,ラ イブラリとローダは慎重にチェックしなければなりません.カーネルが 必要なライブラリをロードできない場合,普通カーネルはエラーメッセージも 出さずに止まってしまうでしょう.
ldd では見えない,動的にロードされるライブラリがシステム に必要とされるかもしれません.
システムが 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 を実行したときに,このファイルが依存関 係で表示されたからです.
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
を組み込む
必要があることを忘れないでください.
モジュール化したカーネルを使っている場合,起動後にブートディスクからど
のモジュールをロードしたいのかを考えなければなりません.バックアップテー
プがフロッピーテープにある場合はftape
モジュールや zftape
モ
ジュールが必要でしょうし,SCSI 機器があるなら SCSI デバイス用のモジュー
ルが必要でしょう.また,緊急時にネットにアクセスしたければ PPP や SLIP
をサポートするためのモジュールも必要になるでしょう.
このようなモジュールは /lib/modules に置きます.また,
insmod
, rmmod
, lsmod
も入れなければなりません.モジュー
ルを自動的にロードするかどうかによって,modprobe
, depmod
,
swapout
が必要になるかどうかも決まります.kerneld
を使うなら
ば /etc/conf.modules も一緒に入れましょう.
しかし,モジュールを使う最大の利点は,必須でないモジュールをユーティリ ティディスクに移しておいて必要な時にロードできる点です.これにより,ルー トディスクで使う容量が減ります.異なる種類のデバイスを多く扱わなければ ならないかもしれない場合,たくさんのドライバを組み込んだ巨大なカーネル を1つ作るよりもこのアプローチの方が好ましいでしょう.
圧縮形式の ext2 ファイルシステムを使う時には RAM ディスクと ext2 のサポートはカーネルに組み込まなければなりません.これらをモジュール として使うことはできません.
/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
が常にルートファイルシステムの
キャッシュを作り直すからです.
ルートファイルシステムの作成が終わったら,このファイルシステムをアンマ ウントし,ファイルにコピーして,圧縮します:
umount /mnt dd if=DEVICE bs=1k | gzip -v9 > rootfs.gz
これが終わったら圧縮形式のルートファイルシステムである rootfs.gz
ができるはずです.この大きさを調べ,フロッピーに収まることを確かめましょ
う.収まり切らない場合には,ファイルをいくつか消しましょう.
ルートファイルシステムのサイズを小さくする場合,
ルートファイルシステムのサイズの削減セクショ
ンが参考になるでしょう.