UbuntuでSynapticパッケージマネージャでkexec-toolsをインストールすれば使えます。
起動したいカーネルと利用したいinitramfs(initrd.img)を含むパーティションがマウントされていなければ、まず、マウントしてください。
端末で
kexec -l 起動したいカーネルの名前(フルパスで) --initrd=利用したいinitramfsの名前(フルパスで) --append="カーネルに渡したいオプション"
で次回の再起動後に利用するカーネルなどを設定できます。再起動せずにすぐに設定したカーネルを起動したい場合、
kexec -e
を実行すれば良いです。
ubuntuのinitramfsにkexec-toolsを組み込む方法
|
synapticなどで、kexec-toolsをインストールします。
「ホーム・フォルダ」にinitrd.imgの展開用のディレクトリ(ここではinit)を作成しておきます。
~$ mkdir init
展開用のディレクトリ(ここではinit)に移動します。
~$ cd init
現在使われているカーネルのバージョンのinitramfsを展開します。
~/init$ gzip -dc /boot/initrd.img-$(uname -r) | cpio -i
kexecに必要な、/sbin/kexecと/lib/tls/i686/cmov/libc.so.6をinitの中にコピーします。
~/init$ cp -p /sbin/kexec sbin/ ~/init$ mkdir -p lib/tls/i686/cmov ~/init$ cp -p /lib/tls/i686/cmov/libc.so.6 lib/tls/i686/cmov/
~/initの内容を再圧縮してintiramfsに戻します。
~/init$ find .|cpio -H newc -o|gzip -9 > ../initrd.img
これで、ホームフォルダのinitrd.imgファイルは、kexecが利用できる状態になっています。
でも、これだけでは、chrootする前の環境で利用できる状態になっているだけで、通常はコマンドラインから作業はできません。つまり、kexecを利用して他の本来起動したいカーネルを起動することはできません。次の作業を行えば、本来起動したいカーネルを選択するメニューを表示させることができます。
改変されたinitrd.imgでkexecを利用するメニューを表示させるための方法
|
~/init$ gedit ./init
で~/init/initを編集します。
以下3行
for conf in conf/conf.d/*; do
[ -f ${conf} ] && . ${conf}
doneを削除。
maybe_break
で始まる行を全て削除。
log_begin_msg "Mounting root file system..."
の行以降を全て削除。
以下を末尾に追記。
[ -d /mnt ] || mkdir -m 0755 /mnt
echo ==========================
echo "Please wait until all the device you want to boot is recognized and then push ENTER key."
echo ==========================
read a
deviceslist=$(blkid|cut -d: -f1)
okdeviceslist=""
for a in $deviceslist
do
umount -l /mnt 2>/dev/null
mount -t auto $a /mnt 2>/dev/null || continue
if [ -e /mnt/vmlinuz -a -e /mnt/initrd.img ]
then
okdeviceslist="${okdeviceslist} $a"
elif [ -n "$(ls /mnt/boot/ -1 2>/dev/null|grep vmlinuz)" ]
then
if [ -e /mnt/boot/initrd.img-$(ls /mnt/boot -1|grep vmlinuz|tail -n1|cut -c9-) ]
then
okdeviceslist="${okdeviceslist} $a"
fi
fi
umount -l /mnt 2>/dev/null
done
i=0
echo ==========================
echo "The device file names and information of partitions will be recognized and are shown below."
echo
for a in ${okdeviceslist}
do
echo $i":"$(blkid|grep "${a}:")
i=$(expr $i + 1)
done
echo
echo "Please type the number of the device file name of the root partition of Ubuntu you want to boot."
readloop()
{
while [ a = a ]
do
read a
if [ $a -ge 0 ]
then
if [ $? = 1 ]
then
echo "Please type number"
continue
elif [ $a -lt "$(echo $*|tr ' ' '\n'|wc -l)" ]
then
break
else
echo "Please type number smaller than $(echo $*|tr ' ' '\n'|wc -l)"
continue
fi
echo "Please type number larger than 0 or 0"
fi
done
}
readloop ${okdeviceslist}
device=$(echo ${okdeviceslist}|cut -d" " -f $(expr $a + 1))
echo "You selected $a:$device"
mount -t auto $device /mntさらに、最新のカーネルのみで起動させれば良い場合には、以下の(1)の枠内を、複数のカーネルを自分で選択したい場合には以下の(2)の枠内を、それぞれ、末尾に追記する。
(1)
if [ -e /mnt/vmlinuz -a -e /mnt/initrd.img ]
then
echo "Please enter commandline parameter to pass to kernel except root=... and ro"
read a
kexec -l /mnt/vmlinuz --append="root=UUID=$(blkid|grep "$device:"|sed -e "s/^.*UUID=\"//"|sed -e "s/\".*//") ro $a" --initrd=/mnt/initrd.img
kexec -e
exit 0
elif [ -n "$(ls /mnt/boot/ -1 2>/dev/null|grep vmlinuz)" ]
then
if [ -e /mnt/boot/initrd.img-$(ls /mnt/boot -1|grep vmlinuz|tail -n1|cut -c9-) ]
then
echo "Please enter commandline parameter to pass to kernel except root=... and ro"
read a
kexec -l /mnt/boot/$(ls /mnt/boot -1|grep vmlinuz|tail -n1) --append="root=UUID=$(blkid|grep "$device:"|sed -e "s/^.*UUID=\"//"|sed -e "s/\".*//") ro $a" --initrd=/mnt/boot/initrd.img-$(ls /mnt/boot -1|grep vmlinuz|tail -n1|cut -c9-)
kexec -e
exit 0
fi
fi
umount -l /mnt
echo "DAMESSU! Please push ENTER key"
PS1='(initramfs) ' /bin/sh -i </dev/console >/dev/console 2>&1
shutdown -r now
exit 0(2)
kernels1=$(ls /mnt/boot/ -1|grep vmlinuz)
kernels=""
i=0
for a in $kernels1
do
if [ -n "$(ls -1 /mnt/boot/initrd.img-$(echo $a|cut -c9-))" ]
then
echo $i":"$(echo $kernels1|cut -d" " -f $(expr $i + 1))
i=$(expr $i + 1)
kernels="$kernels $a"
fi
done
echo "Please type the number of the kernel you want to boot."
readloop ${kernels}
kernel=$(echo ${kernels}|cut -d" " -f $(expr $a + 1))
echo "You selected $a:$kernel"
echo "Please enter commandline parameter to pass to kernel except root=... and ro"
read a
kexec -l /mnt/boot/$kernel --append="root=UUID=$(blkid|grep "$device:"|sed -e "s/^.*UUID=\"//"|sed -e "s/\".*//") ro $a" --initrd=/mnt/boot/initrd.img-$(echo $kernel|cut -c9-)
kexec -e
umount -l /mnt
echo "DAMESSU! Please push ENTER key"
PS1='(initramfs) ' /bin/sh -i </dev/console >/dev/console 2>&1
shutdown -r now
exit 0追記するのは以上。以上のinitの編集作業が終わったら、テキストエディタ(gedit)で「保存」してから、テキストエディタを閉じる。
~/initの内容から、initramfsを作って、~/initrd.imgという名前で保存。
~/init$ find .|cpio -H newc -o|gzip -9 > ../initrd.img
後は、最新のカーネル(/boot/vmlinuz-2.6.??-??-generic)と~/initrd.img(改変したinitrd.img)を起動時に認識できるパーティションにコピーして、それをカーネルローダー(例えばgrub4dosなど)で読み込むように設定すれば良いです。
grub4dosでの設定方法についてはこちらをご覧ください。
改変したinitrd.imgを利用しての実際のUbuntuの起動方法
起動時にカーネルローダーで最新のカーネル(/boot/vmlinuz-2.6.??-??-generic)と改変したinitrd.imgを読み込ませると、
========================== Please wait until all the device you want to boot is recognized and then push ENTER key. ==========================
と表示されるはずです。 USBメディアなどが認識されるまでに少し時間がかかる場合があります。認識されると画面上にメッセージが流れます。 しばらく待ってメッセージが流れなくなったらENTERキーを押してください。ずらずらといろいろなパーティションをマウントするためのメッセージが表示された後で、
========================== The device file names and information of partitions will be recognized and are shown below.
と表示され、その後に
0:/dev/sd・・・
などのように表示されるはずです。 起動したいUbuntuのインストールされたパーティションのラベルやUUIDを探すと良いです。 起動したいUbuntuのインストールされたパーティションの行の先頭の数字をタイプしてENTERキーを押してください。
(2)の場合、
0:vmlinuz-・・・-generic
などのように表示されるはずです。 起動したいUbuntuのカーネルの行の先頭の数字をタイプしてENTERキーを押してください。
Please enter commandline parameter to pass to kernel except root=... and ro
と表示されたら、特別にカーネルに渡したいオプションを入力してください。たとえば、通常まともに表示できない場合に、xforcevesaなどを追記すると良いかもしれません。何もオプションが必要なければ、何も入力しないでください。 ENTERキーを押すと、Ubuntuが起動できるかもしれません。
間違いがありましたら、バシバシ直してください。
謝辞
このページの情報を作成するにあたり、 「 ubuntu の initramfs に kexec-tools を組み込む方法」については、 disklessfun さんからご教示を賜りました。
また、以上の方法は、 grub4dos や kexec-tools, Ubuntu の開発者の方のご尽力があったからこそ実現できるものです。
この場をお借りして御礼申し上げます。