Debian on USB Memory †このページでは、DebianをUSBメモリ上にインストールするための方法を説明する(予定 って、Ubuntuつかえば、まさか速攻完成? 目次 †編集履歴 †2006/08/05 ベース文章を作成 はじめに †
まずは公式ドキュメントを読む †ドキュメントはsargeのようにコードネーム表記ではない。なので、現在のstableの状況と合わせ、どのバージョンのドキュメントを読んでいるかぐらいは念頭に。 公式ドキュメントではsyslinuxというパーティションブートレコードにインストールするタイプのブートローダーを利用しているが、なぜかドキュメント通りに行っても MBR Boot failed と出て進まない。よってこの先はGRUBを利用したバージョンを記述します。 ただ、mkdosfsやcfdiskを用いたパーティショニングなどは有用なので、必ず目を通して、普通に使えるようになっておくこと。 何の役に立つの? †先生が「Vistaになったら使えないかもしれないからロボットの60万のソフト、Debian Sarge用買っちゃった」とか、「Sargeのために毎度HDD切りなおすのやだよねー」とか言うので、必要に迫られました。 ぶっちゃけ人の研究なので誰にも頼まれてないけど、自分の研究がつまんなくなってきたので、ちょっとお遊びでやります。 方法1 †USBメモリからインストーラーを起動、USBメモリ上にインストール †http://lists.debian.or.jp/debian-users/200504/msg00146.html 殆ど上記のとおりでOK。ファイルフォーマットはext3でも大丈夫。 後は普通にUSBメモリからブートして、インストール場所をUSBメモリの別の空き領域に設定すればふつーにインストール可能。 と、書きましたが、実は問題は山積しているものと思われます。下記の[方法2]で触れています。読んでください。もちろん、マシン構成によっては何の苦労も無く起動するでしょうけど。 一応、より良いmenu.lstの肝心なところをベタ書きしておきます。 title Debian GNU/Linux, kernel 2.4 root (hd0,0) kernel /linux ramdisk_size=9650 root=/dev/rd/0 init=/sbin/init devfs=mount,dall rw initrd /initrd.gz boot title Debian GNU/Linux, kernel 2.4 Expert root (hd0,0) kernel /linux DEBCONF_PRIORITY=low vga=normal ramdisk_size=9650 root=/dev/rd/0 init=/sbin/init devfs=mount,dall rw initrd /initrd.gz boot title Debian GNU/Linux, kernel 2.6 root (hd0,0) kernel /linux26 ramdisk_size=10396 root=/dev/rd/0 init=/sbin/init devfs=mount,dall rw initrd /initrd26.gz boot title Debian GNU/Linux, kernel 2.6 Expert root (hd0,0) kernel /linux DEBCONF_PRIORITY=low vga=normal ramdisk_size=10396 root=/dev/rd/0 init=/sbin/init devfs=mount,dall rw initrd /initrd26.gz boot 障害報告 †VAIO UX90(ゼロスピンドルモデル) †Expertでプロセスをトレースすれば分かるが、デバイス認識のためのカーネルモジュールロードの所で、VAIO UX90がUSBを認識しなくなる。(ランプが消える) そして、その後、あんまし検証してない。 testing/sidだったり、カーネルに直接モジュールを埋め込んだり、最新カーネルを配置すれば動くかもしれないけど、他に気を使うことが多そうだし、保留。 http://www.vaio.sony.co.jp/Products/UX1/spec_ownermade_hdd.html 方法2 †debootstrapでuserlandをUSBメモリにインストール †下記を軽く読んでおく。 でも、もっとちゃんと書きます。上記だけじゃ動かないことも多いはずだから。 下準備 †USBメモリが(あえて)sdbで認識され、更に最初のパーティションsdb1を/mntにマウントし、そこにuserlandを作成しようとしていることを念頭に。 mkdosfsやcfdiskを利用してパーティションを切る。ext3でフォーマットする。Primaryパーティション1つで全容量を使用しているとする。作ってみればわかるけど、Xとか導入しなければ256MBでも事足りるサイズだと思う。サイズの大きなUSBメモリを使えば、パーティションを複数作って環境を分けたり/rootとか/homeを共有したりできますね。 debootstrap †# mount /dev/sdb1 /mnt # debootstrap --arch i386 sarge /mnt これで/mnt以下にuserlandのインストール完了。 userlandにkernelの導入 †apt-lineとリゾルバ設定をホストシステムからコピーします。これでchrootした時でもaptが利用できる。ネットワーク設定はホストシステムのものを利用するようなので不要。 # cp /etc/apt/sources.list /mnt/etc/ (ホストシステムのapt-lineを間借り) # cp /etc/resolv.conf /mnt/etc (ホストシステムのリゾルバを間借り) linuxに疎いので詳しくは知らないけど、 # mount -t proc none /mnt/proc としてchroot環境にも/procをマウントしておかないとkernelのインストール時に起こられる。 ホストシステムにgrubがインストールされているなら、 # grub-install --root-directory=/mnt /dev/sdb1 としておく。/dev/sdb1のブートレコードと/mnt/boot/grubに必要なファイルが書き込まれる。 chroot環境に入ります。apt-lineとresolv.confが正しく設定されているかも試す。 # chroot /mnt # apt-get update エラーがでたらapt-lineを修正してください。 上記でファイルはコピーしているかもしれないけど、grubをuserlandに導入するために下記。 # apt-get install grub ホストシステム上からgrub-installを実行していない場合は下記 # mkdir /boot/grub # cp /lib/grub/i386-pc/* /boot/grub # grub --no-floppy grub> device (hd0) /dev/sdb grub> root (hd0,0) grub> setup (hd0,0) grub> quit 実は、この辺り、正しいのか良くわかっていない。chroot環境とホストシステムの関係が分かってないから。 さらにホストシステムに合わせて作成された/boot/grub/device.mapも編集して、少なくとも下記一行を含むようにする。(必要は無いかも?) (hd0) /dev/sda (ブート時はUSBメモリが/dev/sdaになるはず) 次はkernelのインストール。/etc/fstabを編集しないと、なぜか怒られる。 # /etc/fstab /dev/sda1 / ext3 defaults,errors=remount-ro 0 1 proc /proc proc defaults 0 0 また、ホストシステムで # mount -t proc none /mnt/proc を実行していなければ、chroot環境をいったん抜けて、実行。入りなおす。 さぁkernelインストール。一応2.6入れときましょう。 # apt-get install kernel-image-2.x (好きなものを) もしかしたら/vmlinuzとか/initrd.imgといったシンボリックリンク関連で文句を言われるかもしれないが、インストール自体は完了する。文句を解決したければ、 /vmlinuz -> /boot/vmlinuz-2.x (kernel実体) (同様にvmlinuz.old) /initrd.img -> /boot/initrd.img-2.x (initrd実体) (同様にinitrd.img.old) というシンボリックリンクを張っておく。超最新のマシンにも対応したいなら、自分でモジュールを増やしてカーネル再構築しなきゃだめですね。 次は/boot/grub/menu.lstを作る。 # update-grub により自動生成。ただし!ホストシステム側からのデバイス認識順で生成しているっぽいので修正が必要。 root (hd0,0) kernel ・・・ root=/dev/sda1 ・・・(ブート時はUSBメモリが/dev/sdaになるはず) 次にデバイス作成。下記ページを見つけてその必要性を無視して実行したけど、ちゃんとできたので、やってしまえ! # cd /dev # ./MAKEDEV generic と思ったけど、ターゲットシステムべったりでなければ、devfsdとかudev+halでなんとかしてくれそうな気がするので、やらなくても良いと思う。 さらに、一応mbrを作っておきましょ。 # apt-get install mbr # install-mbr /dev/sdb 自動認識という甘い言葉に誘われて、色々も入れておきましょ。はて、kernel 2.6.13からは完全にdevfsがudevで置き換えられたと言う話も聞いたが。 # apt-get install discover1 hotplug devfsd udev hal 日本語keymapにしたい人は †/usr/share/keymaps/i386/qwerty/jp106.kmap.gzを/etc/console/boottime.kmap.gzにコピーしておけば、/etc/initrd/keymap.shが起動時に勝手にやってくれる。 実は、まだ動かないかも †USBメモリの認識と、マウントのタイミング問題 †initrdでusbをscsiエミュレーションで認識して、/dev/sdaデバイスとして利用可能になるタイミングと、initrd RAMディスク(仮root)から実root(/dev/sda)をマウントしに行くタイミングがマシンによっては逆転してしまう。なので、chroot環境での/etc/mkinitrd/mkinitrd.conf中の変数DELAY=5として、仮rootにてモジュールを読み込んだ後/dev/sdaをきちんと認識させるために遅延を与えておく。 これにより、kernelパッケージをインストールしたとき(dpkg-reconfigureでも可)のインストールスクリプトにより生成されるinitrdイメージ中に、DELAY=5という値が反映されるようになる。 USBメモリを押しのけて/dev/sda認識されるデバイスの問題 †SATAとかSCSIのディスクとかを積んでいるマシンはUSBメモリよりも先に/dev/sdaを認識してしまうことがある。なので、initrd RAMディスクの時点で、確実にUSBメモリを先に認識させ、/dev/sdaを確保する必要がある。 因みに、debianのinitrdイメージはgzip圧縮ではないので、世の中にあふれている方法ではマウントできない。 # mount -t cramfs -o loop /boot/initrd.img /initrd のようにすればマウントできる。しかしこれではRead Onlyなので、直接編集は不可能。 どうしても編集したいので、ちょっと変則的なやり方だが、/etc/mkinitrd/mkinitrd.conf中の、 MKIMAGE='mkcramfs %s %s > /dev/null' を MKIMAGE='mkext2fs %s %s > /dev/null' とすれば、ext2フォーマットでinitrdイメージが作成されるので直接マウントして編集できます。ただし、mkext2fsはKNOPPIX関連のMLに投げられた?スクリプトらしい。 #!/bin/bash
# similar to mkcramfs (for use with debian mkinitrd)
# mkext2fs dirname outfile
#
# no options are parsed
#
# Written by: Fabian Franz <mkext2fs@fabian-franz.de>
#
# GPL v.2 - See: `locate gpl.txt`
if [ $# -lt 2 ]
then
echo "Usage: $(basename $0) dirname outfile"
exit 1
fi
TMPDIR=/tmp/$(basename $0).$$
mkdir $TMPDIR
function clean_exit
{
umount $TMPDIR 2>/dev/null
rm -rf $TMPDIR
}
trap clean_exit EXIT
COUNT=$[$(du -s $1 | awk '{ print $1 }' )*2+1000]
dd if=/dev/zero of=$TMPDIR/image count=$COUNT
mke2fs -F $TMPDIR/image
mount -o loop $TMPDIR/image $TMPDIR
cp -a $1/* $TMPDIR
umount $TMPDIR
cat $TMPDIR/image | gzip - > $2
これをchroot環境の/usr/local/binあたりに突っ込んでおいて、dpkg-reconfigureとするとcramfsではなくext2(+gzip圧縮)のinitrd.imgができるので、解凍してloopbackマウント。中身を編集して再圧縮。そのままcramfsのinitrd.imgを置き換えてもdebianではモジュールが足りないのかext2+gzipのinitrd.imgを読めないので、カーネル再構築するか、 # mkcramfs [initrdのマウントポイント] initrd.img としてcramfsに再変換すれば良し。 実際の編集内容。とりあえず[initrdのマウントポイント]/lib/modules/2.x/kernel/drivers/usb/hostに/lib/modules/2.x/kernel/drivers/usb/hostから
をコピーしておく。この際modprobe --show-depends モジュール名 とするとモジュールの依存関係が分かるので便利。 更に、[initrdのマウントポイント]/loadmodulesの内容を編集し、一番上に modprobe -k ehci-hcd modprobe -k ohci-hcd modprobe -k uhci-hcd modprobe -k usb-storage sh -c "sleep 5" と記述する。これによりinitrdがマウントされ、linuxrcが実行され、initrd上の/sbin/initが実行され、loadmodulesが実行される時に、他のscsiデバイスを認識するよりも先にUSBメモリを認識させることができる。 あまり、美しい方法でない気がするので、本当はmkinitrdの使い方を覚えたほうが良いのでしょう。 参考になったドキュメント †
特に最後のリンク先の、 1. lilo によるブート
2. カーネルの起動
3. 仮ルートファイルシステムとして initrd のマウント
4. /linuxrc 実行 (起動時のルートファイルシステム=initrd と本当のルートファイルシステムが異なるときのみ実行される。ふつうは違うはず)
5. 本当のルートファイルシステムをマウント
6. /sbin/init 実行
ところが、Debian では違うの。
1. lilo によるブート
2. カーネルの起動
3. 仮ルートファイルシステムとして initrd のマウント
4. /linuxrc 実行 (ここまではいっしょ)
1. 本当のルートファイルシステム(のデバイス番号)を /tmp/root に保存
2. 本当のルートファイルシステムを initrd と設定
5. 本当のルートファイルシステム(=initrd) をマウント
6. /sbin/init 実行
1. 各デバイスの準備
2. /script 実行(これは call による呼び出しなので、/script 側から /sbin/init 内部で定義された変数や関数を利用できるの)
3. ディレクトリ /scripts 内にある各スクリプトを実行
4. コマンド /sbin/pivot_root を使ってルートファイルシステムを /tmp/root に保存した本当のルートファイルシステムに変更
5. /sbin/init 再実行
Debian ユーザが変更してもよさげな部分は、スクリプト /script と、あとはディレクトリ /scripts 内に配置した各スクリプトくらいかな。
は欲しい情報そのままという感じ。勉強になります。 起動! †つないでUSBメモリからブートして、GRUBが起動する。初回はsingleモード(kernelラインにsingle追加)で起動して、rootログインで、まずはパスワードを設定して。 この辺りの記述は、すげーいろんなことやって回避してたので、この通りやってもうまくいかないことがあるかもしれない。 これで、Debian on USB Memoryは完成するはず!厳密に試してないけど! |