この記事について
「起動しない」「起動が異常に遅い」——インフラ障害の中でも一番焦るのがこの系統のトラブル。今回は電源ボタンを押してからログインプロンプトが出るまでの間に何が起きているかを、実際のコマンドと出力例で追っていく。用語だけ知っていても、実機やクラウドの前でどのコマンドを叩けばいいかわからなければ意味がない。
本題の前に:最低限おさえる5つの用語
いきなり本編に入る前に、この記事で繰り返し出てくる基礎用語だけ先に押さえておく。ここさえ入っていれば、あとはスムーズに読める。
- ファームウェア:マザーボード(基板)に直接書き込まれた、電源を入れた瞬間に動き出す最小限のプログラム。OSのように後から自由にインストールし直すものではなく、ハードウェアに最初から組み込まれている「工場出荷時からいる目覚まし係」のようなもの。
- BIOS:1980年代から使われてきた、最も古いタイプのファームウェアの規格名。
- UEFI:BIOSの後継として作られた新しいファームウェアの規格。今の新しいPC/サーバーはほぼこちらを採用している。
- カーネル:OSの中核部分。CPU・メモリ・ディスクなど、ハードウェアと直接やり取りする司令塔。普段「Linux」と呼んでいるものの実体はこのカーネル部分を指す。
- ブートローダ:ファームウェアからカーネルへの「橋渡し役」。ディスクのどこにカーネルがあるかを探し出し、メモリに読み込んで実行を開始させるだけの、小さくて専門特化したプログラム。
流れは大きく4段階。BIOS/UEFI → ブートローダ(GRUB2) → カーネル+initramfs → systemd。
なぜ1つのプログラムで一気に起動しないのか。答えは単純で、電源が入った直後のハードウェアは非常に非力な状態(限られたメモリ・限られた命令)しか扱えないから。「boot」という単語自体が「bootstrap(自分の靴紐を引っ張って自分を持ち上げる)」の略で、簡素な段階が少しずつ高機能な次の段階を呼び出していく——というのがこの4段階構成の理由。この一言を覚えておくだけで、なぜ毎回“段階”を踏むのかが腹落ちする。
① BIOS/UEFI:電源ONからOSを見つけるまで
電源が入ると、まずファームウェア(BIOSまたはUEFI)が POST(Power-On Self Test、電源投入時の自己診断) でCPU・メモリ・主要デバイスを簡易チェックする。人間で言えば起き抜けに「頭は回るか、手足は動くか」を一瞬で確認するようなもの。異常が無ければ、次に「起動可能なデバイス」を探しにいく。
| Legacy BIOS | UEFI | |
|---|---|---|
| ブート方式 | MBR先頭512バイトのブートコードを実行 | ESP上の.efiファイルを直接実行 |
| パーティション形式 | MBR(容量2TBまで) | GPT(実質無制限、128パーティションまで) |
| セキュリティ | 標準では無し | Secure Boot(署名済みブートローダのみ許可) |
| 起動速度 | 遅め(逐次初期化) | 速め(並列初期化が可能) |
表に出てきた略語も一つずつ:
- MBR(Master Boot Record):ディスクの一番先頭にある、パーティションの位置情報とブートコードをまとめて記録した小さな領域。古い方式。
- GPT(GUID Partition Table):MBRの後継となる、より新しいパーティション管理方式。
- ESP(EFI System Partition):UEFI用の起動ファイルを置いておく専用パーティション。FAT32という形式でフォーマットされていて、ファームウェアがそのまま中身を読める。
- Secure Boot:署名(電子的なお墨付き)が無いブートローダやカーネルの実行を拒否する、UEFIのセキュリティ機能。
具体例:自分のマシンがどちらか確認する
# ディレクトリが存在すればUEFIブートで動いている
ls /sys/firmware/efi 2>/dev/null && echo "UEFI" || echo "Legacy BIOS"
# UEFIのブートエントリ一覧(起動デバイスの優先順位など)
efibootmgr -v
よくある誤解:「BIOSとUEFIは呼び方が違うだけで中身は同じ」ではない。UEFIはファームウェア自身がファイルシステム(FAT32のESP)を読めるため、レガシーBIOSのように決め打ちの512バイトを実行するだけの仕組みより柔軟。2TB超のディスクからの起動やSecure Bootが使えるのもこの構造の違いが理由。
② GRUB2:カーネルを見つけて読み込む
ブートローダの役目は、カーネル本体と次章で説明するinitramfsをメモリに読み込み、制御を渡すこと。Linuxで最も一般的なブートローダであるGRUB2の設定ファイルは、BIOS機なら/boot/grub2/grub.cfg、UEFI機なら/boot/efi/EFI/redhat/grub.cfg(ディストリビューションによりパスは変わる)に置かれる。
具体例:RHEL/CentOS系の実際の構成
RHEL8以降はBLS(Boot Loader Specification)という方式が標準。「カーネルごとの設定を1つの巨大なgrub.cfgに直書きする」のではなく、/boot/loader/entries/というディレクトリの下にカーネル1つにつき1つの小さな設定ファイルを置いていく方式。カーネルを追加/削除するたびに、この小さなファイルが増減するだけなので管理しやすい。
# BLSのエントリファイル一覧(インストール済みカーネルの数だけ存在)
ls -la /boot/loader/entries/
# 現在使われているカーネルパラメータを直接確認
cat /proc/cmdline
# デフォルトカーネルの設定内容を確認
sudo grubby --info=DEFAULT
# 特定カーネルにパラメータを追加する(grub.cfgを直接編集しない)
sudo grubby --update-kernel=ALL --args="intel_iommu=on"
grubbyは、このBLS方式の個別ファイルを安全に書き換えてくれる専用コマンド。grub.cfgを直接編集してはいけない——BLS方式ではgrub2-mkconfigを実行するたびに上書きされる可能性があり、パラメータ変更は基本的にgrubby経由で行うのがRed Hatの推奨。
具体例:grub rescue> が出たときの正体
パーティション操作の失敗やブートセクタの破損で、GRUBが自分の設定ファイルすら見つけられない状態に陥るとgrub rescue>という最小限のプロンプトが出る。これは「GRUBの最初のごく小さいプログラムだけは起動できたが、その先(通常モジュールやgrub.cfg)を見失った」状態。復旧の基本方針は、インストールメディアなどからブートしてrootパーティションをchroot(一時的に別のディスクを本来のrootのように扱う操作)でマウントし、grub2-installでブートコードを再インストール後、grub2-mkconfigで設定を再生成すること。
3行まとめ
・GRUB2の仕事は「カーネルとinitramfsをメモリに読み込んで制御を渡す」こと
・RHEL系はBLS方式で、カーネルごとに/boot/loader/entries/の個別ファイルを持つ
・パラメータ変更はgrub.cfgを直接編集せずgrubbyを使う
③ カーネル初期化とinitramfs:「仮のroot」が必要な具体的理由
GRUBから制御を渡されたカーネルは自己解凍し、CPU・メモリ管理を初期化した上で、次にルートファイルシステム(Linuxのファイル階層の一番の起点、/のこと)をマウントしにいく。ここで1つ、鶏と卵の問題が起きる。
具体例:なぜ仮のrootが必要なのか
たとえばルートファイルシステムがLVM(Logical Volume Manager、複数の物理ディスクをまとめて柔軟にパーティションのように扱う仕組み)上にあるとする。LVMを認識するにはカーネルモジュール(dm_modなど、カーネルに後から追加で読み込める機能部品)が必要だが、そのモジュールはルートファイルシステムの中に入っている。しかしルートファイルシステムはLVMモジュールがないとマウントできない——この矛盾を解消するために、メモリ上に展開する仮の小さなルートファイルシステム(initramfs) を用意し、そこに必要最小限のモジュール(LVM、RAID〈複数ディスクを組み合わせて冗長性や速度を確保する技術〉、暗号化ディスクのドライバなど)を積んでおく。initramfsの中でこれらのモジュールをロードしてから、初めて本当のrootをマウントできるようになる。
つまりinitramfsは「本番用ではない、モジュールを揃えるためだけの捨て台」。役目を終えたらswitch_root(一時的な環境から本番の環境へ実行の主体を切り替える処理)によって本当のrootに切り替わり、initramfs自体は破棄される。
具体例:実際のカーネルログを見る
# 起動時のカーネルメッセージを確認(ドライバ初期化、認識したデバイスなど)
dmesg | less
# 今回の起動分のカーネルログだけをsystemd経由で見る
journalctl -k -b
# 現在使われているinitramfsの中身を覗く
lsinitrd | head -30
よくある誤解:initramfsは「起動後もずっと使われているルートファイルシステム」ではない。役目はモジュールのロードとrootの引き継ぎだけで、switch_rootが実行された時点でメモリからは実質破棄される、あくまで一時的な踏み台。
④ systemd:PID 1からログインプロンプトまで
本当のrootに切り替わった後、カーネルが最初に起動するプロセスがsystemd。PID(Process ID、プロセスに割り振られる識別番号)が1番、つまり一番最初に生まれるプロセスになり、以降すべてのプロセスの祖先(親)になる。
Unit間の依存関係を実例で見る
systemdは、SysVinit時代のように起動スクリプトを1つずつ順番に実行するのではなく、Unit(systemdが管理する「起動する対象」の単位。サービス、マウント、タイマーなどの種類がある)同士に依存関係が無ければ並列に起動することで起動を高速化する。この依存関係を書いているのが各.serviceファイルのAfter=(実行順序)やWants=/Requires=(依存の強さ)。また複数のUnitをひとまとめにした到達点をtargetと呼ぶ(昔のSysVinitで言う「ランレベル」に近い概念で、たとえば「マルチユーザーで使える状態」をまとめてmulti-user.targetと呼ぶ)。
たとえばsshd.service(SSH接続を受け付けるUnit)は「ネットワークが上がってから」かつ「マルチユーザーモードに入るタイミングで」起動したい、という2つの依存を持つ、というのがこの図の意味。実際の設定は次のように書かれている。
[Unit]
Description=OpenSSH server daemon
After=network.target sshd-keygen.target
Wants=sshd-keygen.target
[Service]
ExecStart=/usr/sbin/sshd -D
具体例:起動が遅いときの原因調査
# カーネル/initrd/userspaceそれぞれの所要時間の内訳
systemd-analyze
# 出力例: Startup finished in 9.5s (kernel) + 32.0s (initrd) + 3min 56.8s (userspace)
# どのUnitが一番時間を食っているかランキング表示
systemd-analyze blame
# 起動完了までの「待ち行列(クリティカルパス)」を表示
systemd-analyze critical-chain
# 起動に失敗したUnitだけを一覧
systemctl --failed
systemd-analyze blameは単に「重い処理」を並べるだけなのに対し、critical-chainは「どのUnitが他のUnitの完了を律速しているか」という依存関係のボトルネックを教えてくれる。表面上重そうなサービスを削っても速くならないケースがあるのは、本当のボトルネックがそのサービスではなく、それが待っている別のUnitにあるから。
よくある誤解:「起動が遅い=CPU/メモリ不足」とは限らない。実際にはネットワーク待ちや、あるサービスが別のサービスの完了をひたすら待っているだけのケースが多く、スペックを上げても改善しないことがある。まずsystemd-analyze critical-chainで本当のボトルネックを特定するのが先。
まとめ:電源ONからログインまでのタイムライン
| 段階 | 主役 | やること | 詰まったときに見るコマンド |
|---|---|---|---|
| ① | BIOS/UEFI(ファームウェア) | ハードウェア初期化、起動デバイス探索 | efibootmgr -v |
| ② | GRUB2(ブートローダ) | カーネル+initramfsをロード |
grubby --info=DEFAULT, cat /proc/cmdline
|
| ③ | カーネル+initramfs | ハードウェア認識、本当のrootへ切替 |
dmesg, journalctl -k -b
|
| ④ | systemd(PID 1) | Unitを依存関係に沿って並列起動 |
systemd-analyze blame, critical-chain
|
4段階とも共通しているのは、「前段階が用意した最小限の環境の上で、次段階がより高機能な処理を引き継ぐ」というバトンリレー構造。障害対応でも、まずこの4段階のどこで止まっているかを切り分けるところから始めれば、闇雲に調べるより早く原因にたどり着ける。
次回予告
次回はLinuxディストリビューションの違い編。同じLinuxでもRHEL系とDebian系でパッケージ管理からファイルシステム標準まで何が違うのかを整理する。
参考
- Red Hat Documentation「ブートローダー」「systemd ユニットファイルを使用したシステムのカスタマイズおよび最適化」
- Linux Kernel Documentation(kernel.org)