上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

Linux起動用initスクリプトver.2

http://kiyoandkei.blog68.fc2.com/blog-entry-17.html
のinitを利用して起動した場合、途中で
y
を押すと今までは
grub legacyの設定ファイル(/boot/grub/menu.lst)およびgrub2の設定ファイル(/boot/grub/grub.cfg)を表示させるだけでしたが、さらに、以下の機能を追加しました。

すなわち、それらの設定ファイルを読み込んでそれの中のtitle行(grub legacy)やmenuentry行(grub2)を一覧表示し、それを選ぶと、起動に必要なカーネルとinitramfs、そしてカーネルに渡すオプションを読み込むようにしました。
さらに、それらを使ってkexecをかけるようにしました。
これをメニュー、つまり
(1)設定ファイルの内容の表示
(2)各起動用設定の一覧表示と選択
(3)kexecによる起動
(4)メニューを抜ける
で簡単に選択して実行できるようにしました。

それらの設定ファイルが正常に設定されていれば、起動できます。

initの内容は以下のとおりです。


#!/bin/sh

[ -d /dev ] || mkdir -m 0755 /dev
[ -d /root ] || mkdir -m 0700 /root
[ -d /sys ] || mkdir /sys
[ -d /proc ] || mkdir /proc
[ -d /tmp ] || mkdir /tmp
mkdir -p /var/lock
mount -t sysfs -o nodev,noexec,nosuid none /sys
mount -t proc -o nodev,noexec,nosuid none /proc

grep -q '\<quiet\>' /proc/cmdline || echo "Loading, please wait..."

# Note that this only becomes /dev on the real filesystem if udev's scripts
# are used; which they will be, but it's worth pointing out
if ! mount -t devtmpfs -o mode=0755 none /dev; then
mount -t tmpfs -o mode=0755 none /dev
mknod -m 0600 /dev/console c 5 1
mknod /dev/null c 1 3
fi
mkdir /dev/pts
mount -t devpts -o noexec,nosuid,gid=5,mode=0620 none /dev/pts || true
> /dev/.initramfs-tools
mkdir /dev/.initramfs

# Export the dpkg architecture
export DPKG_ARCH=
. /conf/arch.conf

# Set modprobe env
export MODPROBE_OPTIONS="-qb"

# Export relevant variables
export ROOT=
export ROOTDELAY=
export ROOTFLAGS=
export ROOTFSTYPE=
export IPOPTS=
export HWADDR=
export break=
export init=/sbin/init
export quiet=n
export readonly=y
export rootmnt=/root
export debug=
export panic=
export blacklist=
export resume_offset=

# Bring in the main config
. /conf/initramfs.conf
. /scripts/functions

if [ -z "${noresume}" ]; then
export resume=${RESUME}
else
export noresume
fi

[ -n "${netconsole}" ] && modprobe netconsole netconsole=${netconsole}

# export BOOT variable value for compcache,
# so we know if we run from casper
export BOOT

# Don't do log messages here to avoid confusing usplash
run_scripts /scripts/init-top

log_begin_msg "Loading essential drivers..."
load_modules
log_end_msg

[ "$quiet" != "y" ] && log_begin_msg "Running /scripts/init-premount"
run_scripts /scripts/init-premount
[ "$quiet" != "y" ] && log_end_msg

[ -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*$(ls /mnt/boot -1 2>/dev/null|grep vmlinuz|tail -n1|cut -c9- 2>/dev/null)* ]
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
echo "If you want to search Grub settings, please type y"
echo "If you want to get into busybox, please type zzz"
read aa
fakemore () {
step=$1
num=1
ln=$(wc -l $2 |sed "s/^[^0-9]*//"|sed "s/[^0-9]*$//")
while [ $num -lt $ln ]
do
sed -n "$num,$(expr $num + $step) p" $2
read -p "## Please enter q to quit displaying: " b
if [ a"$b" = "aq" ]
then
break
fi
num=$(expr $num + $step + 1)
done
return
}
if [ -n "$(echo $aa|grep y)" ]
then
if [ -e /mnt/boot/grub/grub.cfg ]
then
echo "/boot/grub/grub.cfg (GRUB2 settings file)is found."
while [ a = a ]
do
echo -n "? 1) show /boot/grub/grub.cfg, 2) select menuentry, 3) kexec -e, 4)end this function : "
read a
if [ "$a" = 1 ]
then
fakemore 10 /mnt/boot/grub/grub.cfg
elif [ "$a" = 2 ]
then
grep menuentry /mnt/boot/grub/grub.cfg | sed -e "s/^[^A-z0-9#]*menuentry *//" > /tmp/menuentries
i=0
num=$(wc -l /tmp/menuentries|tr -s " "|sed -e "s/ *//"|cut -d" " -f1)
while [ $i -lt $num ]
do
i=$(expr $i + 1)
echo $(expr $i - 1):$(sed -n -e "${i}p" /tmp/menuentries)
done
echo "Please type the number of the menu you want to look inside"
readloop "$(cat /tmp/menuentries|tr -d ' ')"
echo "=========================================="
echo "The contents is:"
echo
num=$(grep -A15 -e "$(sed -n -e $(expr $a + 1)p /tmp/menuentries)$" /mnt/boot/grub/grub.cfg|grep -n ^}|sed -n -e 1p|cut -d: -f1)
if [ -n "$num" ]
then
num=$(expr $num - 1)
else
num=15
fi
grep -A $num -e "$(sed -n -e $(expr $a + 1)p /tmp/menuentries)$" /mnt/boot/grub/grub.cfg > /tmp/grubcfg1
cat /tmp/grubcfg1
kernelline=$(grep ^[^A-z0-9#]*linux /tmp/grubcfg1|sed -n -e 1p)
initrdline=$(grep ^[^A-z0-9#]*initrd /tmp/grubcfg1|sed -n -e 1p)
kernel=$(echo $kernelline|sed -e "s/^[^A-z0-9#]*linux *//"|cut -f1 -d" ")
kernelopts=$(echo $kernelline|sed -e "s/^[^A-z0-9#]*linux *//"|tr -s " "|cut -f2- -d" ")
initrd=$(echo $initrdline|sed -e "s/^[^A-z0-9#]*initrd *//"|cut -f1 -d" ")
elif [ "$a" = 3 ]
then
kexec -l /mnt${kernel} --initrd=/mnt${initrd} --append="${kernelopts}"
kexec -e
elif [ "$a" = 4 ]
then
break
fi
done
fi
if [ -e /mnt/boot/grub/menu.lst ]
then
echo "GRUB legacy settings file /boot/grub/menu.lst is found."
while [ a = a ]
do
echo -n "? 1) show /boot/grub/menu.lst, 2) select title, 3) kexec -e, 4)end this function : "
read a
if [ "$a" = 1 ]
then
fakemore 10 /mnt/boot/grub/menu.lst
elif [ "$a" = 2 ]
then
grep title /mnt/boot/grub/menu.lst | sed -e "s/^[^A-z0-9#]*title *//" > /tmp/menuentries
i=0
num=$(wc -l /tmp/menuentries|tr -s " "|sed -e "s/^ *//"|cut -d" " -f1)
while [ $i -lt $num ]
do
i=$(expr $i + 1)
echo $(expr $i - 1):$(sed -n -e "${i}p" /tmp/menuentries)
done
echo "Please type the number of the menu you want to look inside"
readloop "$(cat /tmp/menuentries|tr -d ' ')"
echo "=========================================="
echo "The contents is:"
echo
num=$(grep -A15 -e "$(sed -n -e $(expr $a + 1)p /tmp/menuentries)$" /mnt/boot/grub/menu.lst|grep -n ^[^A-z0-9#]*title *|sed -n -e "2p"|cut -d: -f1)
if [ -n "$num" ]
then
num=$(expr $num - 2)
else
num=15
fi
grep -A $num -e "$(sed -n -e $(expr $a + 1)p /tmp/menuentries)$" /mnt/boot/grub/menu.lst > /tmp/grubcfg1
cat /tmp/grubcfg1
kernelline=$(grep ^[^A-z0-9#]*kernel /tmp/grubcfg1|sed -n -e 1p)
initrdline=$(grep ^[^A-z0-9#]*initrd /tmp/grubcfg1|sed -n -e 1p)
kernel=$(echo $kernelline|sed -e "s/^[^A-z0-9#]*kernel *//"|cut -f1 -d" ")
kernelopts=$(echo $kernelline|sed -e "s/^[^A-z0-9#]*kernel *//"|tr -s " "|cut -f2- -d" ")
initrd=$(echo $initrdline|sed -e "s/^[^A-z0-9#]*initrd *//"|cut -f1 -d" ")
elif [ "$a" = 3 ]
then
kexec -l /mnt${kernel} --initrd=/mnt${initrd} --append="${kernelopts}"
kexec -e
elif [ "$a" = 4 ]
then
break
fi
done
fi
if [ -e /mnt/menu.lst ]
then
echo "GRUB legacy settings file /menu.lst is found."
while [ a = a ]
do
echo -n "? 1) show /menu.lst, 2) select title, 3) kexec -e, 4)end this function : "
read a
if [ "$a" = 1 ]
then
fakemore 10 /mnt/menu.lst
elif [ "$a" = 2 ]
then
grep title /mnt/menu.lst | sed -e "s/^[^A-z0-9#]*title *//" > /tmp/menuentries
i=0
num=$(wc -l /tmp/menuentries|tr -s " "|sed -e "s/^ *//"|cut -d" " -f1)
while [ $i -lt $num ]
do
i=$(expr $i + 1)
echo $(expr $i - 1):$(sed -n -e "${i}p" /tmp/menuentries)
done
echo "Please type the number of the menu you want to look inside"
readloop "$(cat /tmp/menuentries|tr -d ' ')"
echo "=========================================="
echo "The contents is:"
echo
num=$(grep -A15 -e "$(sed -n -e $(expr $a + 1)p /tmp/menuentries)$" /mnt/menu.lst|grep -n ^[^A-z0-9#]*title *|sed -n -e 2p|cut -d: -f1)
if [ -n "$num" ]
then
num=$(expr $num - 2)
else
num=15
fi
grep -A $num -e "$(sed -n -e $(expr $a + 1)p /tmp/menuentries)$" /mnt/menu.lst > /tmp/grubcfg1
cat /tmp/grubcfg1
kernelline=$(grep ^[^A-z0-9#]*kernel /tmp/grubcfg1|sed -n -e 1p)
initrdline=$(grep ^[^A-z0-9#]*initrd /tmp/grubcfg1|sed -n -e 1p)
kernel=$(echo $kernelline|sed -e "s/^[^A-z0-9#]*kernel *//"|cut -f1 -d" ")
kernelopts=$(echo $kernelline|sed -e "s/^[^A-z0-9#]*kernel *//"|tr -s " "|cut -f2- -d" ")
initrd=$(echo $initrdline|sed -e "s/^[^A-z0-9#]*initrd *//"|cut -f1 -d" ")
elif [ "$a" = 3 ]
then
kexec -l /mnt${kernel} --initrd=/mnt${initrd} --append="${kernelopts}"
kexec -e
elif [ "$a" = 4 ]
then
break
fi
done
fi
fi
if [ -n "$(echo $aa|grep zzz)" ]
then
PS1='(kiyoChelp) ' /bin/sh -i </dev/console >/dev/console 2>&1
fi
echo "======================================"
echo "The following kernels seems to be available."
kernels1=$(ls /mnt/boot/ -1|grep vmlinuz)
kernels=""
i=0
for a in $kernels1
do
if [ -n "$(ls -1 /mnt/boot/initrd*$(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 "The following option is suggested to pass to the kernel:"
echo "root=UUID=$(blkid|grep "$device:"|sed -e "s/^.*UUID=\"//"|sed -e "s/\".*//") ro"
echo ""
echo "Please enter commandline parameter to pass to kernel."
echo "If you accept the suggested option, please type nothing."
read a
if [ -n "$a" ]
then
kexec -l /mnt/boot/$kernel --append="$a" --initrd=$(ls /mnt/boot/initrd*$(echo $kernel|cut -c9-)*|tail -n1)
kexec -e
else
kexec -l /mnt/boot/$kernel --append="root=UUID=$(blkid|grep "$device:"|sed -e "s/^.*UUID=\"//"|sed -e "s/\".*//") ro" --initrd=$(ls /mnt/boot/initrd*$(echo $kernel|cut -c9-)*|tail -n1)
kexec -e
fi
umount -l /mnt
echo "DAMESSU! I will try to make you use terminal"
PS1='(kiyoChelp) ' /bin/sh -i </dev/console >/dev/console 2>&1
echo "Please reboot by pressing CTRL+ALT+DEL or ATL+SysRq+R,S,E,I,U,B"
exec run-init ${rootmnt} ${init} "$@" <${rootmnt}/dev/console >${rootmnt}/dev/console 2>&1
panic "Could not execute run-init."



initの内容は以上です。
http://kiyoandkei.blog68.fc2.com/blog-entry-17.htmlと同様にして使うことができます。

実際に、小生の環境では、grub.cfgやmenu.lstの情報を利用して、以下のLinuxを起動できることを確認しました。
すなわち、内蔵HDDのみならず、USB-HDDにインストールされたubuntu10.04、9.10および、Puppy Linux 4.31日本語版(Frugal Install)、Debian、OpenSUSEです。
Mandrivaはカーネルとinitramfsの指定で(hd*,*)が付いているので、menu.lstの選択ではなく、パーティション選択+カーネル選択で、カーネルオプション自動(もしくはroを消去)で起動できました。

BIOSがUSBメディアからの起動に対応していなくて、Grub2やgrub legacy,Grub2でも起動できない場合にでも、これを利用すれば問題なく起動できます。なんせUbuntuのカーネルとmodule(initramfs内)を利用しますので。

いずれ、http://kiyoandkei.blog68.fc2.com/blog-entry-21.htmlと同様に、CDのISOにしたものをWEB上にアップロードしておこうと思います。

今後の課題としては、

1)現在は、/vmlinuzや/initrd.imgまたは/boot/vmlinuz-・・・や/boot/initrd.img-・・・のあるパーティションしか選べないので、そうではないパーティションも選べるようにする。パーティションの一覧を表示する際に、そこに何があるのか、例えば、カーネルがあるのか、grub legacyの設定ファイルがあるのか、ラベルやUUIDはというものがわかりやすく表示されるようにする。

2)grub legacyやgrub2の設定ファイルの内容そのままでは起動できない場合に、簡単にちょっと修正して起動を試みることができるようにする。

3)isolinuxやsyslinuxなどの設定ファイルも利用できるようにする。

4)tputを利用して見やすい表示にする。

5)Windowsの起動には前段階のgrub4dosを利用するようにしていますが、initからも起動できるようにする・・・これは無理かも。

6)マニュアルを整備し、さらに英語に訳して、英語を使う人でも使えるようにする。

7)Ubuntuよりもハードウェア認識能力の強いディストリのカーネルとinitramfsを利用して、ハードウェアの認識能力を高める。2010/6/2時点で、Ubuntu10.04のカーネルは2.6.32-22ですが、
http://www.kernel.org/
によれば、最新のstableなカーネルのバージョンは
2010-05-16に公開された2.6.34
です。新しければ良いというものではないのでしょうけど。
あ、Knoppixでさえ、現時点で利用されているカーネルはUbuntuよりもバージョンが低いので、Ubuntuが一番かもしれません。

などがあります。


2010/10/7

以前使ったこともあるkexec-loaderで、grubの設定ファイルを自動的に探して読み込む機能が追加されたようです。
kiyoshi's helpのこのバージョンの機能と同じです。
今やkiyoshi's helpはsyslinux,lilo,extlinuxの設定ファイルを自動的に検出して読み出して利用できるばかりでなく、
読み出した設定に問題がある場合に若干修正を加えて起動できますし、
さらに、WubiでインストールしたUbuntuをさえ起動できます。
また、zzzでshに入ってコマンドラインで作業もできます。
ファイルシステムをマウントしてその中のファイルを編集したり移動したりすることさえ可能です。
なんてったって、Linuxカーネルを使っているのですから。
関連記事

テーマ : Linux
ジャンル : コンピュータ

コメントの投稿

管理者にだけ表示を許可する

プロフィール

kiyoshi

Author:kiyoshi
FC2ブログへようこそ!

最新記事
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QRコード
since 2011/9/25
現在の閲覧者数:
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。