第5章 システム復旧と代替ブートローダー

LPIC-2 202.2〜202.3 相当

本章は、LPIC-2 202試験の202.2(システム復旧、weight 4)と202.3(代替ブートローダー、weight 2)、合計weight 6に対応します。第3章ではsystemdによる起動のカスタマイズを扱いましたが、実際の障害対応では、通常の起動シーケンスが壊れた状態からどう復旧するかが問われます。検証環境として、Debian/Ubuntu系とRHEL/CentOS系の両方を想定し、コマンド・パスが異なる箇所は両方を併記します(本章の「RHEL/CentOS系」は、コマンド体系が共通するRHEL系ディストリビューション全般を指す表記として使っています。CentOS Linuxは2024年にサポートが終了しており、現在はRocky LinuxやAlmaLinuxが実質的な後継として使われています)。

ブートシーケンスの全体像

BIOS環境とUEFI環境では、電源投入からカーネルが制御を握るまでの流れが大きく異なります。

段階BIOS(レガシー)UEFI
1電源投入電源投入
2POST(Power-On Self Test)UEFIファームウェアの初期化
3MBR(ディスク先頭446バイトのブートコード)を読み込み実行ESP(EFIシステムパーティション)上の.efi実行ファイルを読み込み実行
4ブートローダー(GRUB等)本体の実行ブートローダー(GRUB等)本体の実行
5カーネルの読み込みカーネルの読み込み
6initramfsの展開、ルートファイルシステムのマウントinitramfsの展開、ルートファイルシステムのマウント
7init/systemdへの制御移行systemdへの制御移行

両者の本質的な違いは3・4段階目に集約されます。BIOSはディスク先頭の固定位置からしかブートできない一方、UEFIはファームウェア自体がFAT32ファイルシステムを読み書きでき、ESP上の複数の.efiファイルから起動対象を選択できる、という柔軟性の違いです。

電源投入 BIOS(レガシー) UEFI POST UEFIファームウェアの初期化 MBR実行 (446バイトのブートコード) ESP上の.efiファイルを 読み込み実行 ブートローダー(GRUB等) カーネルの読み込み initramfsの展開 ルートファイルシステムのマウント systemdへの制御移行
UEFIとBIOSのブート経路の比較。両者とも電源投入までは共通ですが、BIOSはPOSTの後にディスク先頭のMBR(446バイトの固定領域)を実行するのに対し、UEFIはファームウェア自体がESP(EFIシステムパーティション)上の.efiファイルを直接読み込んで実行します。ブートローダー以降は同じ経路をたどります。

MBRとGPTの違い

ディスクのパーティション管理方式にも、BIOS時代のMBR(Master Boot Record)と、UEFIで標準的なGPT(GUID Partition Table)という2つの方式があります。

オフセットサイズ内容
0〜445446バイトブートコード(ブートストラップローダー)
446〜50964バイトパーティションテーブル(16バイト×4エントリ、最大4つの基本パーティション)
510〜5112バイトブートシグネチャ(0x55AA、これがないとBIOSは有効なMBRと認識しない)

MBRは合計512バイトという固定サイズの中にすべてを収める設計のため、基本パーティションは最大4つまでという制約があります(拡張パーティションで回避可能)。一方GPTはこの制約がなく、パーティションテーブル自体も冗長化されてディスクの先頭と末尾の両方に保持されるため、MBRより壊れにくい設計になっています。

パーティションタイプID意味
0xEFEFIシステムパーティション(ESP)
0xFDLinux RAID自動検出用パーティション

fdisk -lやgdisk -lの出力でパーティションタイプを確認する際、これらのIDが正しく設定されているかが、そのパーティションが意図通りに認識されるかどうかに直結します。

ESP(EFIシステムパーティション)

UEFI環境では、ブートローダー本体をESP(EFI System Partition)というパーティションに配置します。ESPはFAT32でフォーマットされている必要があります。これは、UEFIファームウェア自体がファイルシステムドライバとしてFAT32の実装しか標準で持たないためで、ext4やNTFSでは代替できません。

$ mount | grep efi
/dev/sda1 on /boot/efi type vfat (rw,relatime,...)
$ ls -R /boot/efi/EFI
/boot/efi/EFI:
BOOT  ubuntu

/boot/efi/EFI/ubuntu:
grubx64.efi  shimx64.efi  mmx64.efi

この行のこの値に注目: /boot/efi/EFI/<distro>/以下のshimx64.efiがSecure Boot対応の起点となるファイル、grubx64.efiが実際のGRUB本体です(両者の関係は後述のSecure Bootの節で扱います)。/boot/efi/EFI/BOOT/には、ファームウェアがどのエントリも見つけられなかった場合の最終フォールバック先として使われるBOOTX64.EFIが置かれます。

efibootmgrの使い方

UEFI環境では、ファームウェアが保持するブートエントリの一覧・順序をefibootmgrコマンドで直接操作できます。

$ sudo efibootmgr -v
BootCurrent: 0002
Timeout: 1 seconds
BootOrder: 0002,0000,0001
Boot0000* Windows Boot Manager  HD(1,GPT,...)/File(\EFI\Microsoft\Boot\bootmgfw.efi)
Boot0001* UEFI: Built-in EFI Shell
Boot0002* Ubuntu  HD(1,GPT,...)/File(\EFI\ubuntu\shimx64.efi)

この行のこの値に注目: BootCurrentは今回実際に起動に使われたエントリ番号、BootOrderはエントリを試す優先順位のリストです。この例では0002(Ubuntu)が最初に試され、実際にBootCurrentも0002なので、意図通りUbuntuから起動したことが分かります。各BootNNNN行の末尾には、そのエントリが指す実際の.efiファイルのパスが表示されます。

$ sudo efibootmgr -c -d /dev/sda -p 1 -L "Ubuntu" -l '\EFI\ubuntu\shimx64.efi'
# -c:新規作成 -d:対象ディスク -p:ESPのパーティション番号 -L:表示名 -l:.efiファイルのパス
BootCurrent: 0002
Timeout: 1 seconds
BootOrder: 0003,0002,0000,0001
Boot0000* Windows Boot Manager
Boot0001* UEFI: Built-in EFI Shell
Boot0002* Ubuntu
Boot0003* Ubuntu
$ sudo efibootmgr -o 0002,0000,0001
# -o:BootOrderを変更。この例ではUbuntu(0002)を最優先にする
BootCurrent: 0002
Timeout: 1 seconds
BootOrder: 0002,0000,0001
$ sudo efibootmgr -b 0003 -B
# -b:対象エントリ番号を指定 -B:そのエントリを削除
BootCurrent: 0002
Timeout: 1 seconds
BootOrder: 0002,0000,0001
Boot0000* Windows Boot Manager
Boot0001* UEFI: Built-in EFI Shell
Boot0002* Ubuntu
$ sudo efibootmgr -n 0002
# -n:次回起動時のみ、恒久的なBootOrderとは別にこのエントリを最優先で使う
BootNext: 0002

この行のこの値に注目: -cで新規作成した直後は、作成したエントリ(Boot0003)がBootOrderの先頭に自動的に追加された状態で表示されます。同じ表示名で複数のエントリ(この例ではBoot0002とBoot0003がどちらも"Ubuntu")が並ぶことがあり、重複登録に気づかずそのままにしておくと管理が煩雑になるため、不要になった側は-Bで削除します。-n実行後に表示されるBootNextは、次回の起動1回限り有効な一時的な指定で、その次の起動からは通常のBootOrderに戻ります。

ファームウェアがブートエントリを認識しなくなった、あるいはOSインストーラでのエントリ作成に失敗した場合は、後述するchroot環境からefibootmgr -cで手動登録することで復旧できます。

UEFI Shellでの操作

多くのUEFIファームウェアには、efibootmgrでの操作すら難しい状況で使える最終手段として、UEFI Shellというコマンドライン環境が組み込まれています。ファームウェアの起動デバイス選択メニュー(多くの機種でF11やF12キー)から起動できます。

Shell> map                     # 認識しているファイルシステム(fs0:、fs1:...)の一覧を表示
Shell> fs0:                     # fs0という名前のファイルシステムに移動
FS0:\> cd EFI\ubuntu
FS0:\EFI\ubuntu\> ls
FS0:\EFI\ubuntu\> shimx64.efi   # .efiファイル名を直接入力して実行

mapコマンドで表示されるfs0:・fs1:は、ファームウェアが認識しているFAT形式のパーティションに便宜的に振られた名前です。目的の.efiファイルまでcdで移動し、ファイル名をそのまま入力すれば実行できます。GRUBの設定もESPも壊れていない場合の、efibootmgrによる恒久登録より一段階手前の緊急起動手段として使えます。

Secure Bootとshim

Secure Bootは、UEFIファームウェアが、暗号署名されていないブートローダー・カーネルの実行を拒否する仕組みです。マルウェアによるブートローダーの改ざんを防ぐことが目的ですが、そのままではMicrosoftの鍵で署名されていない一般のLinuxカーネルやモジュールが起動できなくなってしまいます。

この問題を解決するのがshimです。shim自体はMicrosoftの鍵で署名された小さなブートローダーで、その先でGRUBやカーネルを検証する際には、ディストリビューションベンダーの鍵、または利用者自身が登録した鍵(MOK: Machine Owner Key)を使います。

自前ビルドのカーネルがSecure Boot環境で起動しない理由: 本章や前章で扱ったように自前でカーネルをビルドした場合、そのカーネルにはディストリビューションベンダーの署名が付きません。Secure Boot環境ではshimがこれを検証できず、起動が拒否されます。対応するには、(1)MOKを自分で生成しmokutil --importで登録した上で、自前のカーネル・モジュールに自分の鍵で署名する、または(2)検証・学習目的であればファームウェア設定でSecure Boot自体を一時的に無効化する、のいずれかが必要です。

NVMeからのブート

NVMe SSDのデバイスファイルは、SATA/SCSIディスク(/dev/sdaのような命名)とは異なる命名規則を持ちます。

$ lsblk
NAME        SIZE
nvme0n1     500G
├─nvme0n1p1  512M
└─nvme0n1p2  499.5G

nvme0n1p1は「1台目のNVMeコントローラ(nvme0)配下の1番目のネームスペース(n1)の1番目のパーティション(p1)」を意味します。現在の主要なUEFIファームウェアはNVMeブートに標準対応していますが、古い一部のマザーボード・サーバーではファームウェアレベルでのNVMe対応が不完全で、追加のオプションROMやファームウェアアップデートが必要になる場合があります。導入前には、対象ハードウェアのファームウェアがNVMeブートに対応しているかをベンダーの仕様で確認しておくべきです。

GRUB 2の構造

GRUB 2の設定ファイル/boot/grub/grub.cfg(RHEL系では/boot/grub2/grub.cfg)は、直接編集するものではなく、/etc/default/grub(既定値)と/etc/grub.d/以下のスクリプト群から自動生成されます。

/etc/default/grubのパラメータ意味
GRUB_TIMEOUTメニュー表示から自動起動までの待機秒数
GRUB_DEFAULT既定で選択されるメニューエントリ(番号、またはsavedで前回起動したものを記憶)
GRUB_CMDLINE_LINUXすべてのカーネル起動エントリに共通で渡すカーネルパラメータ
GRUB_DISABLE_OS_PROBER他のOSの自動検出(os-prober)を無効化するかどうか
/etc/default/grub の設定例
GRUB_TIMEOUT=5
GRUB_DEFAULT=saved
GRUB_CMDLINE_LINUX="net.ifnames=0 biosdevname=0"
GRUB_DISABLE_OS_PROBER=false

/etc/grub.d/以下には00_header・10_linux・30_os-prober・40_customのような番号付きスクリプトが並び、ファイル名の数字順に実行されてgrub.cfgの各部分を出力します。40_customは利用者が自由に追記してよい唯一のファイルで、それ以外のスクリプトはパッケージ更新で上書きされる可能性があります。

$ sudo grub-mkconfig -o /boot/grub/grub.cfg   # 直接呼び出す場合の書式(update-grubの実体)
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-6.6.32
Found initrd image: /boot/initrd.img-6.6.32
Found linux image: /boot/vmlinuz-5.15.0-1057-aws
Found initrd image: /boot/initrd.img-5.15.0-1057-aws
done
$ sudo update-grub                             # Debian/Ubuntu系のラッパー(出力は上と同じ)
$ sudo grub2-mkconfig -o /boot/grub2/grub.cfg   # RHEL系
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-6.6.32
Found initrd image: /boot/initramfs-6.6.32.img
done

この行のこの値に注目: grub-mkconfig -o ファイルという書式そのものが示す通り、実際にはこのコマンドは標準出力にgrub.cfgの内容を生成し、-oで指定したファイルへリダイレクトしています。Generating grub configuration file ...以降に表示される進捗メッセージは標準エラー出力に流れる別の情報で、Found linux image:の行が検出したカーネルの数だけ並びます。update-grubは内部で同じgrub-mkconfigを呼び出すだけなので、表示される内容は同一です。

よくある間違い:grub.cfgを直接編集する: grub.cfgはgrub-mkconfigが実行されるたびに、/etc/default/grubと/etc/grub.d/の内容から丸ごと再生成されます。grub.cfgを直接手で書き換えても、次にカーネル更新などで再生成が走った瞬間に変更が失われます。恒久的な変更は必ず/etc/default/grubまたは/etc/grub.d/40_customに対して行い、その後update-grub/grub2-mkconfigを実行してください。

grub-installは、ブートローダー本体をディスクへ(再)インストールするコマンドで、BIOS環境とUEFI環境で指定する引数が異なります。

$ sudo grub-install /dev/sda                       # BIOS環境:ディスク全体を指定(MBRに書き込む)
Installing for i386-pc platform.
Installation finished. No error reported.
$ sudo grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=ubuntu
# UEFI環境:ディスク全体ではなくESPのマウント先を指定し、.efiファイルを配置する
Installing for x86_64-efi platform.
Installation finished. No error reported.

この行のこの値に注目: どちらの環境でも、最終行にInstallation finished. No error reported.と表示されれば成功です。Installing for i386-pc platform./x86_64-efi platform.の部分で、実際にどちらのモード(BIOS用のブートコードか、UEFI用の.efiファイル一式か)でインストールされたかを確認できます。指定した--targetと一致しない場合は、引数の指定ミスを疑います。

grubシェルでの手動起動

設定ファイルが壊れて通常起動できない場合でも、GRUB自体が最小限の対話環境を提供しているため、そこから手動でカーネルを起動できます。次の手順で、grub.cfgが機能しない状態からの手動起動を実演します。

  1. 起動時にGRUBメニューでcキーを押す: 通常のメニュー画面から、モジュールが読み込まれ補完も効く「grubシェル」に入ります。ここで確認すべきこと: プロンプトがgrub>になっていることを確認します(さらに壊れが深刻な場合はgrub rescue>という、より制限された最小プロンプトが表示されます)。
  2. lsでパーティションを確認する:
    grub> ls
    (hd0) (hd0,gpt2) (hd0,gpt1)
    ここで確認すべきこと: どのパーティションがルートファイルシステムかを推測します。判断が難しい場合はls (hd0,gpt2)/のように中身を覗いて確認できます。
  3. ルートパーティションを指定する:
    grub> set root=(hd0,gpt2)
    ここで確認すべきこと: 指定を間違えるとこの後のカーネル読み込みで該当ファイルが見つからずエラーになるため、前段のlsの結果と照らし合わせます。
  4. カーネルとinitrdを指定する:
    grub> linux /vmlinuz root=/dev/sda2
    grub> initrd /initrd.img
    ここで確認すべきこと: linux行のroot=は、grubのset rootとは別物で、カーネル自身に「本来のルートファイルシステムはどこか」を伝えるパラメータです。両者を混同しないよう注意してください。
  5. bootで起動する:
    grub> boot
    ここで確認すべきこと: 正常に起動できたら、ログイン後に必ずupdate-grub/grub2-mkconfigを実行し、grub.cfgを恒久的に復旧させます。この手動起動はあくまでその場限りの応急処置で、設定ファイル自体は直っていません。

GRUB Legacyとの違い

GRUB 2以前に使われていたGRUB Legacyは、設定ファイル名や記法が異なります。古い文書やレガシー環境の保守で遭遇することがあるため、対応関係を押さえておきます。

項目GRUB LegacyGRUB 2
設定ファイルmenu.lst(直接編集する)grub.cfg(自動生成、直接編集しない)
デバイス指定の記法root (hd0,0)set root=(hd0,gpt1)
パーティション番号0始まり((hd0,0)は1番目のパーティション)1始まり((hd0,1)やGPTでは(hd0,gpt1)が1番目)

特にパーティション番号が「0始まりか1始まりか」は、GRUB LegacyからGRUB 2への移行で最も混同しやすい違いです。GRUB Legacyの(hd0,0)は1番目のパーティションを指しますが、同じ意味をGRUB 2で書く場合は(hd0,1)(MBR)または(hd0,gpt1)(GPT)になります。

起動しないときの復旧手順(症状別)

起動トラブルは症状によって取るべき対応が異なります。次の順に切り分けます。

  1. GRUBメニューすら表示されない: ブートローダー自体が破損・消失している可能性が高い状態です。後述のLive USB+chroot手順で復旧環境に入り、grub-installを再実行してブートローダーを再インストールします。
  2. GRUBメニューは出るがカーネルパニックで停止する: カーネル自体、またはinitramfsの破損が疑われます。GRUBメニューから旧カーネルを選んで起動を試み、起動できたら新しいカーネル向けのinitramfsをupdate-initramfs -u/dracut -fで再生成します。
  3. Kernel panic - not syncing: VFS: Unable to mount root fsが表示される: カーネルがルートファイルシステムを見つけられない・マウントできない状態です。主な原因は、initramfsに必要なドライバ(LVM/RAID等)が含まれていない、またはroot=指定やUUIDが実際のパーティションと一致していないことです。
  4. emergency modeに落ちる: 多くの場合/etc/fstabの記述ミス(存在しないUUIDの指定など)が原因です。journalctl -xbで直近の起動ログを確認し、どのマウントが失敗しているかを特定します。今後同様の問題を避けるため、必須ではないマウントエントリにはnofailオプションを付けておくと、そのデバイスが見つからなくても起動自体は継続できます(詳細は「ファイルシステムの運用」の章を参照)。
  5. rootパスワードを忘れた: 次節の手順で対応します。

rootパスワードを忘れた場合の対処

警告:この手順は物理/コンソールアクセスを持つ人なら誰でも実行できます: 以下の手順はGRUBパスワードなどの追加保護がない限り、サーバーに物理アクセスできる(あるいはコンソールにアクセスできる)人であれば誰でも実行できてしまいます。これは裏を返せば、サーバールームの入退室管理やリモートコンソールへのアクセス制御自体が、root権限を守る最後の砦になっているということでもあります。
  1. GRUBメニューで対象エントリを選びeキーで編集画面に入る。
  2. linuxで始まる行の末尾にinit=/bin/bash(またはよりsystemdに沿ったsystemd.unit=rescue.target)を追記し、Ctrl+Xで起動する。
  3. init=/bin/bashの場合、ルートファイルシステムがread-onlyでマウントされるため、まず書き込み可能に切り替える。
    bash-5.1# mount -o remount,rw /
  4. passwdコマンドでrootのパスワードを再設定する。
    bash-5.1# passwd root
  5. SELinuxが有効な環境(RHEL系)では、init=/bin/bash経由での変更はSELinuxのラベル付けを経由しないため、touch /.autorelabelを実行してから再起動し、次回起動時に全ファイルのSELinuxラベルを再付与させる。これを怠ると、パスワードは変わってもSELinuxのラベル不整合でログインやサービス起動に失敗することがあります。
  6. 再起動して通常通りログインできることを確認する。

Live USBからのchrootによる復旧

起動が完全にできない状態からの復旧では、Live USBやレスキューモードで別のLinux環境を起動し、対象システムのルートパーティションをマウントした上でchrootし、あたかもそのシステム自身が起動しているかのようにgrub-installやupdate-grubを実行するのが定番の手順です。

$ sudo mount /dev/sda2 /mnt                  # 壊れたシステムのルートパーティションをマウント(正常時は無出力)
$ sudo mount /dev/sda1 /mnt/boot/efi          # UEFI環境ではESPも忘れずにマウント(正常時は無出力)
$ for d in dev proc sys run; do sudo mount --bind /$d /mnt/$d; done   # 正常時は無出力
$ sudo chroot /mnt
(chroot)$ grub-install /dev/sda && update-grub
Installing for i386-pc platform.
Installation finished. No error reported.
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-6.6.32
done
(chroot)$ exit
exit
$ for d in run sys proc dev; do sudo umount /mnt/$d; done   # 正常時は無出力
$ sudo umount /mnt/boot/efi /mnt   # 正常時は無出力

この行のこの値に注目: chroot /mntを実行するとプロンプトが変わらないディストリビューションもあるため、以降のコマンドが本当にchroot先で実行されているかは、echo $$やcat /etc/os-releaseで確認するのが確実です(この例ではプロンプトに便宜的に(chroot)$と表記しています)。exitでchrootを抜けると通常のプロンプトに戻り、続けてアンマウントの手順に進みます。アンマウントは、マウントした順序と逆(子ディレクトリから親へ)で行わないと、device is busyのようなエラーで失敗することがあります。

なぜdev/proc/sys/runのバインドマウントが必要なのか: chrootは、指定したディレクトリを新しい「/」として見せかける仕組みですが、それだけでは/mnt以下は静的なファイルの集まりに過ぎません。/devにはデバイスファイル、/procにはカーネルが提供する実行時のプロセス・システム情報、/sysにはデバイス・ドライバの実行時情報、/runにはsystemdなどが使う実行時の一時データが、それぞれ通常のシステムでは動的に提供されています。これらを--bindマウントで chroot先に持ち込んでおかないと、grub-installのようなコマンドがディスクデバイス(/dev/sda)にアクセスできなかったり、実行中のカーネル情報を参照できずに失敗したりします。アンマウントは、マウントした順序の逆(子から親へ)で行うのが安全です。

rescue.targetとemergency.targetの違い

ターゲットマウントされるもの起動しているサービス主な用途
rescue.target/etc/fstabに基づき、ローカルファイルシステムを通常通りマウント基本的な下回りのサービス(udev等)は起動、それ以外は最小限特定のサービス設定を修正したい場合
emergency.targetルートファイルシステムのみをread-onlyでマウント(fstabの他のエントリはマウントしない)ほぼ何も起動しない、最小のシェルのみファイルシステム自体が壊れている、あるいはfstabの記述ミスで通常起動が止まる場合
$ sudo systemctl rescue      # 稼働中のシステムから、レスキューモードへ切り替え

Broadcast message from root@web01 on pts/0 (Fri 2026-08-21 09:40:03 JST):

The system is going down to rescue mode NOW!
$ sudo touch /forcefsck      # 次回起動時に、ルートファイルシステムのfsckを強制的に実行させる(正常時は無出力)

この行のこの値に注目: systemctl rescueを実行すると、ログイン中の全端末にBroadcast message ...という警告が届き、その直後にほとんどのサービスが停止してレスキューシェルへ切り替わります。リモートSSH接続で作業している場合、このコマンドの実行そのものによって接続が切断される可能性があるため、事前にコンソールアクセスの手段を確保してから実行するべきです。

/forcefsckファイルを作成しておくと、多くのディストリビューションでは次回起動時にこのファイルの存在を検知して、通常はスキップされるクリーンな状態のファイルシステムに対してもfsckを強制実行します。systemdベースの環境では、起動時のカーネルパラメータにfsck.mode=forceを追加することでも同様の効果が得られます。

代替ブートローダー

名称対応するファイルシステム/用途
SYSLINUXFAT形式のパーティションから起動(USBメモリのブート用途などで利用)
EXTLINUXext2/3/4などのLinuxネイティブなファイルシステムから直接起動
ISOLINUXISO9660形式(CD/DVDイメージ)から起動。isolinux.bin・isolinux.cfgを使用
PXELINUXネットワーク経由(PXEブート)での起動に特化

ISOLINUXは、BIOS環境の光学メディア起動規格であるEl Toritoに対応した形でisolinux.binを配置します。近年はUSBメモリからもISOイメージをそのまま書き込んで起動できる「ハイブリッドISO」が主流で、これはisohdpfx.binというMBR相当のコードをISOイメージの先頭に付与することで、CD起動・USB起動の両方に対応させる仕組みです。

PXELINUXは、ブート時に複数の設定ファイル名を順番に探索する仕組みを持っています。

  1. クライアント固有のUUIDを16進数表記にしたファイル名
  2. MACアドレスを01-で始まる形式にしたファイル名
  3. IPアドレスの16進数表記を、末尾の桁から1桁ずつ削りながら順に試す(最長一致から最短一致へ)
  4. どれにも一致しなければdefaultファイル

この探索順により、特定のMACアドレスやIPアドレス範囲のクライアントにだけ異なる設定(特定のOSインストーラを起動させるなど)を割り当てることができます。

PXEブートの全体像

PXE(Preboot eXecution Environment)は、ハードディスクにOSをインストールせずに、ネットワーク経由でOSやインストーラを起動する仕組みです。

DHCPサーバー側でPXE用に追加するオプションの例
next-server 192.168.1.10;      # TFTPサーバーのアドレス
filename "pxelinux.0";          # BIOS環境向けのブートファイル
# UEFI環境向けには filename "uefi/shim.efi" のように別ファイルを指定することが多い

クライアントはまずDHCPでIPアドレスと上記のnext-server(TFTPサーバーのアドレス)・filename(最初に読み込むブートファイル名)を取得し、続けてTFTPでブートローダー本体をダウンロードして実行します。BIOS環境かUEFI環境かをDHCPサーバー側で判別するために、DHCPのArchitecture(option 93、クライアントアーキテクチャ)オプションが使われます。クライアントがDHCPリクエストの中でこのオプションを申告し、DHCPサーバーはその値に応じてBIOS用(pxelinux.0)とUEFI用(shim.efiやgrubx64.efi)で異なるfilenameを返す、という振り分けが可能になっています。

systemd-boot

GRUB以外の選択肢として、UEFI専用のシンプルなブートローダーであるsystemd-boot(旧gummiboot)があります。GRUBのようにブートローダー自体が複雑な設定言語やスクリプトを解釈するのではなく、ESP上に置かれた個々のカーネルエントリを、UEFIファームウェアが直接列挙して選択させる、非常にシンプルな構造が特徴です。

$ sudo bootctl install     # systemd-bootをESPにインストールし、ファームウェアのブートエントリに登録
Created "/boot/efi/EFI/systemd" directory.
Created "/boot/efi/EFI/BOOT" directory.
Created "/boot/efi/loader" directory.
Created "/boot/efi/loader/entries" directory.
Copied "/usr/lib/systemd/boot/efi/systemd-bootx64.efi" to "/boot/efi/EFI/systemd/systemd-bootx64.efi".
Copied "/usr/lib/systemd/boot/efi/systemd-bootx64.efi" to "/boot/efi/EFI/BOOT/BOOTX64.EFI".
Created EFI boot entry "Linux Boot Manager".
$ bootctl list             # 現在登録されているブートエントリを一覧表示
Boot Loader Entries:
        type: Boot Loader Specification Type #1 (.conf)
         title: Ubuntu (6.6.32)
            id: ubuntu.conf
        source: /boot/efi/loader/entries/ubuntu.conf
       version: 6.6.32
         linux: /vmlinuz-6.6.32
        initrd: /initrd.img-6.6.32
       options: root=UUID=1a2b3c4d-... rw quiet

この行のこの値に注目: bootctl installの出力にあるCopied ...行は、systemd-boot本体のバイナリがESPのどこに配置されたかを示し、最後のCreated EFI boot entry "Linux Boot Manager".で、UEFIファームウェア側のブートエントリ登録まで完了したことが分かります。bootctl listの各項目のsourceは、そのエントリに対応する.confファイルの実際のパスで、内容を直接編集したい場合はこのファイルを開きます。

/boot/efi/loader/entries/ubuntu.conf の例
title   Ubuntu
linux   /vmlinuz-6.6.32
initrd  /initrd.img-6.6.32
options root=UUID=xxxx-xxxx rw quiet

この.confファイル1つが、GRUBのmenuentry1ブロックに相当します。設定ファイルの生成スクリプトを介さず、テキストファイルを直接置くだけでエントリが増える点がGRUBとの大きな違いです。

U-Bootの概要

組み込み機器やARMベースの機器の世界では、U-Bootが広く使われています。サーバー用途のGRUBやsystemd-bootとは異なり、シリアルコンソールからの対話的操作、ネットワークブート、NANDフラッシュ・SDカードからの起動など、組み込み機器特有の要件に対応しています。U-Bootの設定はbootcmd(起動時に自動実行されるコマンド列を格納した環境変数)とbootargs(カーネルに渡す起動パラメータを格納した環境変数)という2つの環境変数を中心に構成されます。LPIC-2では、U-Bootについては名称と大まかな位置づけを押さえておく程度で十分です。

エラーメッセージと原因の対応表

症状・メッセージ主な原因
GRUBメニュー自体が表示されないMBR/ESPのブートコードが破損・消失。chroot環境でのgrub-install再実行が必要
error: file '/boot/grub/i386-pc/normal.mod' not foundGRUBの一部ファイルが破損・欠落。grub-installとupdate-grubの再実行で修復を試みる
Kernel panic - not syncing: VFS: Unable to mount root fsinitramfsに必要なドライバがない、またはroot=の指定が実際のパーティションと一致していない
起動中に emergency mode へ落ちる/etc/fstabの記述ミス(存在しないUUID等)。journalctl -xbで原因特定
UEFIでSecure Boot有効時に自前カーネルが起動しないカーネル・モジュールに有効な署名がない。MOKの登録と署名、またはSecure Boot無効化が必要

本章で扱ったinitramfsの生成・カーネルの入れ替え手順の詳細は「カーネルのビルドとカスタマイズ」の章で、fstabの書式やnofailオプションの詳細は「ファイルシステムの運用」の章で扱っています。

確認クイズ

Q1. UEFI環境で、ブートローダーの実行ファイルが置かれる専用のFAT32パーティションを何と呼びますか?

解説: UEFI環境では、ESP(EFI System Partition)と呼ばれるFAT32のパーティションに.efi形式のブートローダーが置かれます。

Q2. MBRの構造のうち、ブートコードが格納される部分のサイズはどれですか?

解説: MBRの先頭446バイトがブートコード、続く64バイトがパーティションテーブル、末尾2バイトがブートシグネチャです。

Q3. 次のefibootmgr -vの出力から、実際に今回の起動に使われたエントリはどれですか?
BootCurrent: 0002
BootOrder: 0002,0000,0001
Boot0000* Windows Boot Manager
Boot0002* Ubuntu

解説: BootCurrentが0002であることから、実際に今回の起動に使われたのはBoot0002(Ubuntu)のエントリです。

Q4. UEFIファームウェアが、暗号署名されていないブートローダー・カーネルの実行を拒否する仕組みを何と呼びますか?

解説: Secure Bootは、署名されていないブートローダーやカーネルの実行をファームウェアが拒否する仕組みです。

Q5. grub.cfgを直接手で編集してはいけない理由として適切なものはどれですか?

解説: grub.cfgはgrub-mkconfig(update-grub等)実行のたびに/etc/default/grubと/etc/grub.d/から丸ごと再生成されるため、直接編集した内容は次の再生成で失われます。

Q6. grubシェルでの手動起動時、linux行に指定するroot=と、set root=の違いとして正しいものはどれですか?

解説: set rootはGRUB自身がカーネルファイル等を読み込むためのパーティション指定であり、linux行のroot=はカーネルが本来のルートファイルシステムをマウントするための指定で、別の目的を持つ設定です。

Q7. GRUB Legacyの記法(hd0,0)が指すパーティションを、GRUB 2のGPT環境の記法で書くとどうなりますか?

解説: GRUB Legacyのパーティション番号は0始まりのため(hd0,0)は1番目を指しますが、GRUB 2は1始まりのため、GPT環境での同じパーティションは(hd0,gpt1)と表記します。

Q8. emergency modeに落ちる典型的な原因と、その調査に使うコマンドの組み合わせとして適切なものはどれですか?

解説: emergency modeに落ちる典型的な原因は/etc/fstabの記述ミスで、journalctl -xbで直近の起動ログを確認し失敗したマウントを特定します。

Q9. Live USBからchrootで復旧作業を行う際、/dev・/proc・/sys・/runを--bindマウントする必要がある理由はどれですか?

解説: chrootは指定ディレクトリを新しい/として見せかけるだけなので、/dev・/proc・/sys・/runが提供する動的な実行時情報を利用するには、これらを明示的にバインドマウントする必要があります。

Q10. PXELINUXが設定ファイルを探索する順序として正しいものはどれですか?

解説: PXELINUXはUUID、MACアドレス、IPアドレスの16進表記(末尾から1桁ずつ削りながら)、最後にdefaultの順で設定ファイルを探索します。

Q11. BIOS環境かUEFI環境かをDHCPサーバー側で判別し、異なるブートファイルを配布するために使われるDHCPオプションはどれですか?

解説: DHCPのArchitectureオプション(option 93)でクライアントのアーキテクチャが申告され、これに応じてサーバー側でBIOS用・UEFI用のブートファイルを振り分けられます。

Q12. systemd-bootの設定方式がGRUBと大きく異なる点はどれですか?

解説: systemd-bootはgrub-mkconfigのような生成スクリプトを介さず、loader/entries/以下に.confファイルを直接置くだけでブートエントリが追加される、シンプルな構造を特徴とします。