カーネルの再構築のめも

※上記の広告は60日以上更新のないWIKIに表示されています。更新することで広告が下部へ移動します。

カーネルを再構築する時の参考に。


動作確認時の注意
ターゲットの環境で、「今動いているもの」を、「これから試そうとしている方法」で試してから、
新しいカーネルの動作確認をしましょう。そうしないと、大はまりする事があります。

例えば、テスト用のカーネルが他のカーネル混ざらないように、/boot/test/ に、新しいvmlinuzなどを置く場合を考えてみます。
※GRUBの場合は、/boot/直下にコピーした場合と挙動が変わります。(しかも、vmlinuzなどのファイル名によって、挙動が変わります。)

例:(ファイル名は適当です)
今動いているものを/boot/vmlinuz-123、これを/boot/test/vmlinuz-123-copyにコピーして試す場合。
cd /boot
mkdir test
cp vmlinuz-123 test/vmlinuz-123-copy

LILOの場合:
設定ファイルを編集(/etc/lilo.conf)
設定を反映(lilo)
再起動して、テスト用のメニューを選んでみると・・うまく起動するはず。

※GPTディスクの場合は、ELILOなどを利用します。 (ELILOは使った事がないので、誰か補足を。)
※(基本的にNGですが) GRUBと併用する時は、特に設定に注意しましょう。(MBRに入れずに、ルートパーティションに置くとか)
 GRUBをメインのブートローダにしている場合、起動できなくなると、直すのが面倒です。(LILOと似た手順で直りますが・・)
※LILOがメインのブートローダの場合は、起動できなくなった場合でも・・・(lilo.confの内容自体が間違えていなければ)
 CD/DVDでブートして、HDDをマウントして、chrootして、liloすれば(LILOの設定は)復活するはず・・です。
 (HDDのマウントとchrootが面倒な時は、setupでごにょg・・慣れていないと危なそうなので自己責任で)

結論(LILOの場合、というより、Slackware環境の場合):
特に気にせず、普通に新しいカーネルを試せそうです。(必要なライブラリが・・という問題はありますが。)
※ただし、systemdを採用しているディストリビューションでは、initrdの扱いに注意して下さい。
 (/sbin/initが、/lib/systemd/systemdにリンクされている環境)
 ブートローダの設定やカーネルのせいかと思いきや・・の場合が多いです。
 参考になりそうなページ:systemdを本番運用してわかったこと ※図を見て、イメージをつかみましょう
 検索キーワード:「systemd without initrd」、「udev」など
initrd無しで起動可能なカーネルでも、systemdを使用している環境では、initrdを使用しないと、はまります。


GRUB2の場合:
必要に応じて、設定ファイルを編集(/etc/grub.d/40_Customとか) ※ここが、はまるポイント。
update-grub (または、grub-mkconfig) で、/boot/grub/grub.cfg設定を反映します。
※GRUB Legacyでは/boot/grub/menu.lstなどを編集するだけ(編集後に何もせず再起動してよかった)でしたが、
 GRUB2では、/etc/default/grubや、/etc/grub.d/*などに設定を書き込み、
 update-grubなどのコマンドで、grub.cfgに設定を反映させます。

grub.cfgを見てみると、40_Customで設定した内容が書き込まれているようです。
※ 見る箇所は、40_Customの部分です。

再起動して、テスト用のメニューを選んでみると・・あれっ?大抵は起動しません。
何やら、Kernel Panicとか、マウントに失敗とか、(initramfs)で止まるとか、想定していたのとは違う結果に。
(これはGRUB以外の問題だと思いますが・・)
(/boot/直下にvmlinuz-123-copyを置いた場合は動作しますが、別の問題(10_linuxの自動検出)との兼ね合いもあるので、要注意。)

例:/boot/直下にテスト用のvmlinuzへのリンクを置いてみます。
ln -s /boot/test/vmlinuz-123-copy /boot/vmlinuz-123-copy
update-grub (または、grub-mkconfig) で、設定を反映します。
(/boot/にそのままvmlinuz-123-copyを置いてもよいですが・・・・・きっと、はまります。)
※今回は、/boot直下にファイルを置くだけです。10_linuxは編集しません。
※ファイル名が/boot/vmlinuz-*の場合は、10_linuxが「自動的に」拾ってくれます ※ここも、はまるポイントだったりしますが・・

grub.cfgを見てみると・・・今度は、設定が反映されていないようです。
※「偶然」設定が正しく反映される場合もあります。
※ 見る箇所は、10_linuxの部分(デフォルトのメニュー)です。
※ 元の設定から変わっていない場合は、再起動時にうまく立ち上がってしまうので、気づかなかったりします。
 (立ち上がらなければ、再起動時にeキーでメニューを編集しようと思って、あぁぁーーっとなるのですが・・)

何がいけなかったのでしょうか。
じつは、10_linuxは、設定反映用のコマンド(update-grubなど)を実行した時に、
/boot/vmlinuz-*のファイル名などを見て、自動的にgrub.cfgの設定(しかも、デフォルトで起動するカーネルや初期ディスク(initrd)の指定)を変えてしまうのです。
(ファイル名を降順に並べて、一番大きいものが選ばれているかと思います。)
なので、/boot/に置くファイルの名前には、かなり注意しないといけません。
/boot/に、色々な名前のvmlinuzやinitrd.imgが散らばらないようにしましょう。(vmlinuzとinitrd.imgの組み合わせも自動になっているので)

色々実験した結果(Debian8(Kernel 3.16.0)で実験してみました):
40_Customに、Linuxのmenuentryを作っても、正しく動作しないようです。
(10_linuxが生成した内容とまったく同じ内容でも、正しく動作しません。起動時にeキーで編集モードに入って同内容にしても同じ。)

10_linuxが自動生成した、Advanced options (/boot/にあるvmlinuz-*を全てメニューにして並べたもの) からの起動は、可能でした。
(ようするに、40_Customの編集は不要で、自動生成するエントリを使った方が無難ということ)

結論(GRUBの場合):
vmlinuz (必要に応じて、initrd.img)は、/boot/ 直下に、直接置く(お勧めしません)か、別の場所に置いてリンクを貼りましょう。
/boot/直下のvmlinuz-*やinitrd.img-*は、自動検出の対象、かつファイル名に応じてgrub.cfgに反映される設定が変わるので、ファイル名が重要です。
テスト用に/boot/直下に置くvmlinuz-*やinitrd.img-*は、降順ソートで、現在動いているvmlinuz(ソートの先頭)よりも後に来るファイル名にします。
現在動いているvmlinuzより前に来てしまうと、起動時のデフォルトになってしまいます。

40_Customを編集するのではなく、10_linuxによって自動生成されるエントリを使いましょう。
Advanced optionsなどの名前のメニューに全部入っているはず!

参考: GRUB ※menuentryを書く時の参考に。
※1回試すだけなら、起動時のGRUB画面でeキーを押して、vmlinuzなどのファイル名を変える方が楽です(デフォルトでは保存されません)。
 ちなみに、ファイル名などは、Tab補完できます。(root=で使うUUIDは出ないようです・・)




GRUB(GRUB2)を使う場合の注意
細かい部分は、ディストリビューションによって変わると思いますが・・

必ず、/boot/grub/grub.cfgの内容を確認しましょう。
特に、/boot/の中に、ファイル名がvmlinuzやkernelから始まるファイルを増やした時は、最大限の注意が必要です。

/etc/grub.d/10_linuxなどに、「それっぽいものを自動検出して、設定を変える」系のスクリプトが入っています。
ファイル名の候補(/boot/vmlinuz-*など)を逆順ソートしたものの先頭が、デフォルト(linux行に書いてあるvmlinuz)として使われるようです。
(ようするに、バージョンが新しいものを自動選択する仕組み。)

例:(数字は適当なので存在しないかも)
/boot/vmlinuz-3.0と/boot/vmlinuz-3.1があったら、3.1の方。
/boot/vmlinuz-3.0と/boot/vmlinuz-3.0.1があったら、3.0.1の方。
/boot/vmlinuz-3.0.1と/boot/vmlinuz-3.0.1-aがあったら、3.0.1-aの方。
/boot/vmlinuz-3.0.1-aと/boot/vmlinuz-3.0.1-bがあったら、3.0.1-bの方。

grub-mkconfigやupdate-grubの表示に注意しましょう。
認識したvmlinuzやinitrdのリストを表示するかと思います。
ここに、必要なものが表示されたか確認しましょう。

/boot直下に無いvmlinuzやinitrdは、表示されない・・はずです。※はまるポイント
このリストに表示されないvmlinuzなどを使用すると、
Linux起動時に、ルートがマウントできないとか、Kernel Panic VFSとか、
「原因が何だか分からないエラー」に悩まされます。

ちなみに、リンクは読めるので、/boot直下にないファイルでも、
/boot直下に、vmlinuzなどから始まる名前のリンクを作ればいけるはず!


ノート

とりあえず、まとめ。とっておいた方がよい情報:config、EFI、GRUB、(GPT)
ついでに、押さえておいた方がよい用語:GRUB2、(GRUB Legacy)、UEFIモード、GPT(特に、EFI(GPT)ラベル→partdの、mklabel gptとかmsdosとか)

もし、レンタルサーバで使うためにカーネルをビルドしたい場合は、サーバにデフォルトでインストールされているディストリビューションの、/bootと/etcのコピーを手元に残しておくことを強くお勧めします。
/boot/config・・・とかgrub/grub.confとか、/etc/(略) とか。ディストリビューションごとにファイル構成が少し異なるので、ファイル単位でコピーする場合は、コピーし忘れに注意しましょう。
Kernel Panicが起きるけど、元の設定ならどうなのさ?という時にものすごく役に立ちます。(大抵、元のファイルを消した後に気づくので)
/var/log/* もあると便利です。/var/log/messagesとかね!

できればEFI関連の情報も取得しておきましょう。/sys/firmware/efiが無いけど、ディスクをフォーマットしたらEFIシェルが出てくるとか・・ありがちなので。
(普通は、ディスクをフォーマットした後に気づくので、/sys/firmware/efiがあるか確かめられません。)
参考:
 UEFIの解説ページ ※「UEFI ファームウェアのビット数を調べる」の辺り
/sys/firmware/efi ディレクトリが存在するかどうか確認してください。存在するときはカーネルは EFI モードで起動されています。

SlackwareのデフォルトのブートローダはLILOなので、GRUB関連の情報は少ないです。(GRUB・・) ※LILOは2015/12で開発終了らしい

GPT(GUIDパーティションテーブル)は、EFIのおまけみたいなもの。
大抵は、EFIを使う場合はGPTを推奨とかで、そのためにGRUBを使う・・という、遠い眼になりすぎて、100Km先のライオンが見えそうなセットになっているので、
「動く」設定は、とっておきましょう。
MBR-GPTという、MBR(マスターブートレコード)を併用する方式は、動かない環境もあるので、GPT専用ディスクになっている場合もあります。(ここも押さえるポイント)
要するに、GRUB専用(LILOが使えない)だから、カーネルを訓練しないとインストールできないぞ!な環境になっている事が多いので、がんばって動かしましょうということ。
Slackware 14.1も、64bit版限定でUEFI対応のはずなんだけどなぁ・・・(ローカル仮想環境のUEFIでは動くけど、レンタルサーバーのUEFIだとインストーラが黒画面とか、もう)

One of the big changes in Slackware 14.1 is support for systems running UEFI firmware (x86_64 Slackware edition only).
We've added several new packages for UEFI, including elilo, GRUB 2, and efibootmgr

関連のありそうな項目:configの中を"EFI"で検索すると、見つかるはず。
トラップになりそうなな項目:CONFIG_EFI_STUB (QEMUとの相性が・・ってどこかに)


カーネル変更後のKernel Panicについて (起動時にKernel Panic not syncing などの表示が出る場合)



 カーネルを変更した後にマシンを起動すると、Call Trace: ・・・ intel_pmu_init・・・Kernel Panic not syncing と表示されたら、おそらくこの問題。
 QEMN/KVMなどの環境で、-cpu SandyBridgeなどの場合に、Intel P-stateが正しく処理されていないらしいです。
 もしこの現象が起きた場合は、CONFIG_X86_INTEL_PSTATE の設定を変えて試してみましょう。
 参考:
 ArchLinux CPU 周波数スケーリング ※「CPU 周波数ドライバー」のあたりを読みましょう
 VirtualBoxで Slackware64 14.1(kernel 3.10.16) (英語) ※下の方に、スクリーンショットなどがあります

 補足:"Kernel Panic not syncing"で検索すると、"sedisable=0"とかSELinuxを無効に・・などの検索結果が出てきますが、
 SlackwareはデフォルトではSELinuxは入れない状態でコンパイルしてあると思います。
 sedisableやenforceといったブートオプションは、その機能を有効にしてカーネルをコンパイルしなおさないと使えません。
 (当然、インストール用DVDで起動した時も、SELinux関連のコマンドは使えなかった・・はずです)
 なので、レンタルサーバなどでデフォルトでインストールされている環境をつぶす時には注意しましょう。(SELinuxを有効にしたままとか・・)
 何で?と思った人は、このあたりを見るといいと思うよ。セキュリティをやってるやつらは(ry

 関連のありそうな項目:configの中を"SECURITY_"で検索すると、見つかるはず。
 CONFIG_SECURITY_SELINUXとか、SMACKとか、TOMOYOとか、APPARMORとか、YAMAとか・・
 LSMも、この仲間。(LSMの上に、SELINUXとかを乗せているはず)


カーネル変更後のKernel Panicについて (起動時にKernel Panic VFS などの表示が出る場合)


 はまらないために、設定ファイル(/boot/config・・・または/usr/linux/.configなど)の先頭部分を見ておくことをお勧めします。(特に、レンタルサーバでvirtio(仮想化I/O)が入っている環境)
 この先頭部分は、menuconfigなどで直接いじれない項目ですが、ここに"CONFIG_ARCH_DEFCONFIG"とう項目があり、"arch/x86/configs/x86_64_defconfig"(あるいはi386_defconfig)などの値が設定されていると思います。この値が示すフォルダは、/usr/src/linux/arch/x86/configs/にありますので、ざっくりと中を見ておきましょう。
 このフォルダに、"kvm_guest.config"というファイルがある場合(カーネル2.6.36.rc4以降)は、特によく見た方がよいです。CONFIG_9P_FSなど、設定をうっかり忘れそうな項目が結構あります。
 (設定を忘れると、Kernel Panicが発生します。他のディストリビューション(CentOS6とかRedHat7とかUbuntuとか)でもアップデート時にいつのまにか外されているらしいですが・・)
 ちなみに、Slackware14.1(64bit版)の場合も、しっかり外されています。某レンタルサーバにインストールしようとすると、インストーラが立ち上がらないから、ふぁっ!ってなるけどね。
 (他のディストリビューションでアップデート履歴を管理してなかったらアウトだろうな・・)
 Kernel Panic VFSとか、マウントできないとかだったら、おそらくこの問題。(ext4などをモジュール(設定を"y"ではなく"M")にしてコンパイルしたとかでなければ)
 ※/(ルート)があるパーティションのファイルシステム(ext4など)は、モジュールにするとアウト。
 モジュールにしていなくても、mkinitrd -m ext4とかするとアウト。(-m ext4をつけずにmkinitrdすれば大丈夫。) ext4と依存関係のある、jbd2とかmbcacheにも注意。
 参考:
 QEMU/KVM VirtFS(9Pfs over virtio)のセットアップ(英語)
 QEMU/KVM バージョン履歴(旧) ※使える機能と使えない機能を見分けるために。CPUのホットプラグに対応してないとか色々。
 VirtFS (スライド、英語) ※11枚目(ブロックダイアグラム)を見る。VirtFSのイメージがつかめるはず。
 9P 概要(スライド、英語) ※28枚目を見る。fscacheを使うのはEXPERIMENTAL(ほとんどテストしてない)

 関連のありそうな項目:configの中を"VIRT"とか"9P"で検索すると、見つかるはず。
 トラップになりそうな項目:"HOTPLUG_CPU"で検索すると出てくる項目(未検証) など。



で、インストールDVDすら立ち上がらない環境で、どうやって確かめるのさ?という場合。

補足:例が古くなっています。注意。(/boot/直下以外に置くと動作が怪しげな環境もあるので)

デフォルトでインストールされている環境を使ってテスト。
ディストリビューションが違っても、同じLinuxの仲間。なんとかなる。

混ざらないように、適当なフォルダ(/boot/test/とか)を作って、そこに、試したいカーネルのvmlinuz-??(と、initrd-??.gz)を入れます。
間違って必要なファイル(vmlinuzとか、initrd.gzとか)を消したり上書きしたりしないように要注意!
※通常は、間違って上書きしないように、ファイル本体をvmlinuz-??とかinitrd-generic-??.gzに置いておいて、
ln -sで、vmlinuzやinitrd.gzにリンクしてあります。
(特に、initrd.gzは、mkinitrdのデフォルトの出力先なので、ファイル本体をinitrd.gzに置かないようにしましょう)

LILOを使える場合は、/etc/lilo.confを編集
lilo.confの例:
(略)
# 今動いてる方
image = /boot/vmlinuz
root = /dev/sda1
initrd = /boot/initrd.gz
label = Linux
read-only
# テストする方 (initrdがある場合は、"initrd = /boot/test/initrd-test.gz"も追加)
image = /boot/test/vmlinuz-test
root = /dev/sda1
label = LinuxTest
read-only

lilo.confを保存した後に、
# lilo
すると
Added Linux *
Added LinuxTest
などと表示されます。(テストする方でinitrdを使っている場合は、最後に"+"が付くはず)
これで、/boot/mapが更新されたはずなので、システムを再起動して、LinuxTestの方を選びます。
テストの方がうまく起動できなくても、もう一度再起動してLinuxの方を選べば、通常起動するはずです。


使えるのがGRUBのみだったよ、どうしよう?の場合。

補足:例が古くなっています。注意。(/boot/直下以外に置くと動作が怪しげな環境もあるので)

LILOを入れてしまえ(うひひ というのは、やめておきましょう。
たぶん起動できなくなって、泣きます。


ELILOなら!(ry ※ELILOは、2014年に開発終了となりました(だったよね?
いや、ありだと一瞬思いましたが、GRUBの設定を覚えましょう。
詳しくは、この辺りに(宙を指しながら)・・・いる人を捕まえて聞いて下さい。

おまけ:適当なので、一応調べてから使ってね!
(UEFIかと思ったらBIOSモードになってたよ・・とか色々条件があるらしいので、ちゃんとした説明はGRUBページに譲ります)
※使うのはGRUB2だと思うので、EFIパーティションの説明は省きます (タイプ0xEF00で、FAT32で、/boot/efiとかにマウントして、GRUB Legacyを使うときに色々入れるあれのことです)

/boot/grub/grub.cfg : 設定内容が反映されるファイル。
再起動する前に、ちゃんと「正しい」設定が反映されたか確認した方がよさげ。

/etc/default/grub : GRUBで使うデフォルト値。
GRUB_CMDLINE_LINUX_DEFAULTに設定した値は、Linuxの起動項目(10_linuxが生成する項目メニューの、linuxと書いてある行)に付きます。
※lilo.confのappend=みたいなものです。メニュー毎に付くので、addappend=に近いかも。

/etc/grub.d/??_* : grub.cfgに書き込む内容を返す(標準出力に出力する)シェルスクリプト。数字が小さいほうから順に呼ばれます。
00~05あたりまでは、共通の設定が入っているので、それ以降を使います。
10_linuxが、Linuxの起動設定ファイル。(このファイルは、基本的に編集しません。)

40_customなどのファイルを作って、カスタム設定項目を書き込みます。

40_custom の例 (あくまで例です。そのまま書き込まないように!)
menuentry "Test Kernel" {
    echo "Loading Test Kernel..."
    load_video
    insmod (必要なモジュール。モジュール毎に1行ずつ。モジュールは/boot/grub/i386-pcなどに入っています。(/lib/modulesにあるモジュールとは異なります))
    echo "Loading linux kernel..."
    linux /boot/test/vmlinuz-test root=UUID=(ルートパーティションのUUID。blkidコマンドなどで見られます。) ro console=tty0
}
/boot/grub/grub.cfgの下の方を見ると、Linux用のエントリ(menuentry)があると思います。それを参考にするとよいかと思います。

この例で使っている"load_video"は、grub.cfgの上の方にある(かもしれない)、function load_videoです。
(中で、insmod efi_gopとかinsmod vbeとか色々呼んでいます。)
grub.cfgに書かれている場合は、/etc/grub.d/のどこか(00_header など)にあるはずです。
grub.cfgに書かれていない場合は、別の名前になっているかもしれません。
もし見つからない場合は・・参考資料「GRUB」の中の「"No suitable mode found" エラー」のあたりを参照しながら、必要な項目を書き込みましょう。

linuxという行は、lilo.confの、"image = "みたいなものです。
同じ行の中のrootは、lilo.confの、"root = "みたいなものです。
/(root)と/bootが別パーティションにある場合は、
"set root=" で、/bootの入っているパーティションを指定します。(であってる?)
(linux行にある、"root=" は、/(root)が入っているパーティションです)


設定ファイルの編集が終わったら、
# grub-mkconfig -o /boot/grub/grub.cfg
で、設定を反映しましょう。きっと、妖精さんが、/boot/grub/grub.cfg に素敵な内容を書きこんでくれたはず!
※妖精さんが眠りながら作ってくれるので、たまにおかしなことが起こります。できあがったgrub.cfgを、さくっと眺めておきましょう。


参考:GRUB


最終更新:2015年05月30日 09:28