CLI・CUIなワークステーションを作る へ

番外編 grub

 別項で述べたとおり,IBM-PC互換機におけるHDDの伝統的な管理方法である,「基本領域は4つまで,最後の基本領域については,任意の数の論理領域に分割することができ,そのことで見かけ上数の制限のない領域を作れる」の下で,複数のOSをインストールして選択して起動させる場合に筋がいい方法論は,1つのプログラムでOSの起動までやってしまうのではなく,領域の選択だけを行い,各領域にその領域からOSを起動するプログラムを置くというものです。この方法論の下で一番使いやすいプログラムは,領域の選択を行うプログラムとしてMBMを採用することです。実際,実験としてOSをインストールしては削除して領域を切り直してということをやっているコンピューターについては,MBMで運用しています。
 一方,領域と運用するOSが確定したと言っていいコンピューターにおいては,わざわざ2段階でやるほどのものではないという考え方もあります。そういうコンピューターにおいては,grubを使っています。
 grubについては,現在grub2と言われるver2が主に使われており,Lubuntuでは自動でインストールされますし,FreeBSDではpkg install grub2でgrub2をインストールすることになります(pkgからはgrubはインストールできない)。2015年2月現在Gentoo LinuxとGentoo/FreeBSDについては,自動インストールはされない以上には未確認です。

grub 2

 pkg install grub2でインストールした後,grub-installでgrub本体をディスクの先頭領域にインストールしちゃっても問題ありませんでした。
 grub 2は,grubのversion 2で,今までのgrubがLegacy grubとも呼ばれているのに対し,「grub 2」と呼ばれています。
 Legacy grubと異なり,grub 2では,設定ファイルである/boot/grub/grub.cfgを直接手書きすべきではないとする指摘があります。しかし,個人的な経験でいうと,Linuxでgrub-mkconfigとかupdate-grubで自動生成させようとしても,たいていはFreeBSDの領域を認識してくれないため,結局手書き修正せざるを得ず,しかも以下の手順で手書きすることで無事動いているため,自動生成の勉強を最近は全くしていません。
 メニューである/boot/grub/grub.cfgがないとそもそも動いてくれません。grub 2の/boot/grub/grub.cfgは,こんな感じです。

冒頭
timeout=30
 選択時間の設定で,この場合は30秒待って選択がなければデフォルトに指定されたOSを起動します。
冒頭の次
default=0
 デフォルトで起動させるOSが以下の何番目に記述されているかを指定します。先頭が0,以下1,2……と続きます。

以下は,各OSごとの記述を並べていくだけです。grub 2では,

menuentry "OS名" {
OSを動かすためのコマンド群(1行に1命令)
}

が基本形です。

1 FreeBSDを起動させる場合
 1台目のHDDの最初の領域にインストールしてあるのを起動させる例です。

menuentry "FreeBSD"{
set root=(hd0,1)
parttool (hd0,1) boot+
chainloader +1
}

set root=(hd0,1)
rootの値は,起動するHDDと領域を指定します。
1台目のHDDの番号は1ではなく0,以下同様です。
これに対し,領域は1からスタートです。
「set 項目 = 値」の形式です

parttool (hd0,1) boot+
「parttool HDDと領域 命令」の形式です。
当該領域をactiveにする命令が boot+ というわけです。windowsやFreeBSDではactiveにしないと,それだけで起動できません。Linux系の場合はたいてい不要のはずです。

chainloader +1
当該領域の先頭セクタに制御を移します→そこにブートローダーがあれば起動できるという仕掛けです。
FreeBSDは基本的には1つの基本領域をFreeBSD側で複数のスライスに分割して使用しますが,ブートローダーがその基本領域の先頭に入ります。そこに制御を移してgrub 2の仕事は終了ということになります。

2 他の領域に入っているLinuxを起動させるためのgrub 2に制御を移す場合
 Lubuntuは,インストール時に,grub 2をインストールする領域を,当該ドライブの先頭の他,Linuxのために確保された(swap以外の)領域にすることもできます。そうすることによって,そのgrub 2に制御を渡すことができれば,grub 2を使った2段階起動も可能です。(MBMより筋は悪いけど……。)
 Lubuntu的には/dev/sda6,FreeBSD的には/dev/ada0s6の先頭のgrub 2に制御を渡す場合です。

menuentry "Lubuntu 16.04 LTS"{
set root=(hd0,6)
chainloader +1
}

1で説明したとおり,Linuxについては,領域をactiveにする必要はないので,「parttool (hd0,6) boot+」を削っています。また,FreeBSDが原則「領域内にスライスを作って対応→領域自体は1個でいい」のに対し,Linuxでは「分けるごとに領域が必要だが,基本領域か拡張領域かは問わない」ため,複数OSインストールの場合は,拡張領域に入ることが多いと思います。それでも領域番号を指定するだけで問題なしです。(ちなみにこれ,(hd0,msdos6)でも動くのですが,「基本領域でないけどいいの?」って聞かれてしまって,returnを押す回数が1回増えてしまいます。)

3 他の領域に入っているLinuxを直接起動する場合
 例えばLubuntuを動かすための設定をそのままコピー&ペイストで,直接起動できるはずなのですが……。まだ試していません。

4 windowsを起動する場合

menuentry "Windows"{
set root=(hd1,1)
parttool (hd1,1) boot +
chainloader +1
}

「当該領域をactiveにし」「基本領域の先頭に制御を渡すと動く」点がFreeBSDとwindowsは共通しているので,(っていうか,Linuxがかなり異端)ほぼ同じ記述になります。

5 とある機械における特殊設定のために必要な情報
 詳細は下に書きましたが,1つのドライブにまるごとwindowsを入れ,FreeBSDとかを他のドライブを入れていた機械で,「windowsの入ったドライブだけつなげば普通に動くけど,普段は他のディスクもつなぎ,かつMBMとかgrubとかで選択したいから,windowsの入ったディスクにはMBMとかgrubとか入れたくないんだよね」ってわがままを通すために,ちょっとトリッキーなことをしています。Legacy grubにおいてはmapとswapの組合せで複数行で処理することになっていましたが,grub2では,

drivemap -s (hd0) (hd1)

と-sオプションをつけることで,1行にまとめることができるようです。

Linux系の場合

 設定ファイルは,grub.cfgではなく,grub.confです。
 「sudo nano /etc/grub.d/40_custom」で,注意書き部分の下に,メニューに加えるものを書き加えた後,「sudo update-grub2」で/etc/default/grubが自動生成されます。
(HP2133に,FreeBSD9.1とLubuntu13.10を入れようとしたところ,なぜかLubuntu13.10のインストールが失敗するため,WattOS R7.5のLXDE版を入れた際にも,FreeBSDを自動認識しなかったため,WattOSでターミナル起動し,sudo nano /etc/grub.d/40_customを入力して編集したということがありました。)

grub起動直前にshiftを押せばメニュー画面が出るけど,
そうしないといきなりOSが動いちゃう場合
「sudo nano /etc/default/grub」で
「#GURB_HIDDEN_TIMEOUT=0」がコメントアウトされていない
=#がついていないことが考えられるので,
もしそうなら直した上で,保存し,「sudo update-grub2」

grub

 grub 2登場後は,Legacy grubとも呼ばれています。私は,Gentoo Linuxによるものしか使っていませんでした。grub.confの設定のとおりに動作します。grub.confの自動生成コマンドもあったはずですが,当時のGentoo Linuxのハンドブックでは手書きする前提で説明していました。

冒頭 timeout=30
 選択時間の設定で,この場合は30秒待って選択がなければデフォルトに指定されたOSを起動します。
冒頭の次 default=0
 デフォルトで起動させるOSが以下の何番目に記述されているかを指定します。先頭が0,以下1,2……と続きます。

これ以下は当該OSについて起動コマンドを記述するもので,OSごとに繰り返していきます。

windowsの場合
1行目 title Windows
選択画面におけるタイトル表示です。「title 」以下の文字列がそのまま使用されます。
2行目 root (hd0,1)
起動するHDDとその領域を指定します。どちらも0からスタートします。HDDについてはBIOSにとっての1台目が0,2台目が1の順です。一方領域については1番目の領域が1,2番目が2です。0はHDD全体の先頭領域です。
この指定だとhd0の1番目の領域にOSを起動するプログラムが入っていることを示します。
3行目 makeactive
2行目で指定した領域をactiveにします。windowsやFreeBSDではactiveにしないと,それだけで起動できません。Linux系の場合はたいてい不要のはずです。
4行目 chainloader +1 当該領域の先頭セクタに制御を移します→そこにブートローダーがあれば起動できるという仕掛けです。

FreeBSDの場合
title FreeBSD(x86) 9.3
root (hd0,1)
makeactive
chainloader +1

特殊な扱い
私の場合,emperorにおいては,当初PATAの3.5インチHDDにwindows,SATAの3.5インチHDDにBSD等他のOSを入れ,なおかつ,PATAしかつながない時にはMBMとかgrubなしにwindowsが起動するように仕掛けました。その後PATAを使わずSATAの2台使用に変えてからも,この仕掛けを維持しました。そのため,BIOSが認識するHDDの順番を入れ替える処理をしています。仕掛けについて若干説明すると,非windows側のHDDにMEMとかgrubをインストールし,そちらを先にBIOSに認識させ,そのHDDを一旦(hd0),windowsが入っているHDDを(hd1)とさせます。その後,windowsが入っている方を(hd0)と認識しなおすよう命じた上で,旧(hd1)側から起動するように命じます。
具体的には
map (hd0) (hd1)
map (hd1) (hd0)
でBIOSが認識したHDDの順番を入れ替えた上で,
root (hd1,0)
と,入れ替える前の領域を指定することになります。
 ちなみにこの方法論だと,windowsが入っていない方のHDDの先頭領域にgrub起動用のプログラムが入り,それ自体は特別に消す手段をとらない限り消えません。一方,それが呼び出す先のgrub本体は,新たにOSをインストールすると消えてしまうので,起動用のプログラムがシェルを起動させます。
 この場合,新たなOSのインストール前に/boot/grub/grub.cfgを待避させ,インストール後grubをインストールし,「grub-install /dev/ada0」を実行した上で,待避させた/boot/grub/grub.cfgを戻しておくと,問題なく動くようになります。

 ちなみに2013年3月5日当時,PATAのHDDに「windowsXp」,SATAのHDDに「FreeBSD9.1」「PC-BSD9.1」「gentoo linux 3.7.10」「Lubuntu 12.10」をこの順で入れ,gentoo linuxのgrubのインストール先をSATAの先頭にし,Lubuntuの方はLubuntuの先頭にgrub2をインストールするようにしましたが,なぜかLubuntuが起動できず,仕方なくMBMをCDに焼いて,Lubuntuを起動する時は,MBMの入ったCDから起動するようにしていました。また,gentooはPATAをつながないと動くのに,つなぐとなぜか「/デバイスが不正」ってエラーを出して動かなくなります。
 2015年2月25日現在,FreeBSDの9以前の32bit版できることのうちの1つを除いてFreeBSD10.0の64bit版でもできることが判明し,これに1本化したことで,現在のemperorは1台にwindows,もう1台の一部にFreeBSD10.0の64bit版を入れ,残りをあけて運用しています。

(2013.3.5.初版)
(2017.4.19.修正)

CLI・CUIなワークステーションを作る へ