起動時間の分析
起動が遅いと感じたら、原因を勘で探す前に計測します。systemd-analyze は、ファームウェア・ブートローダ・カーネル・ユーザ空間それぞれにかかった時間を要約して表示します。systemd-analyze blame を使えば、起動に時間のかかったサービスを降順に並べられ、ボトルネックの特定に直結します。さらに systemd-analyze critical-chain で、起動完了までの依存の連鎖(クリティカルパス)を確認できます。どのサービスが全体を待たせているかが数字で分かるため、無効化や設定見直しの判断材料になります。
「最近サーバの起動が遅い気がする」「再起動してからログインできるまでがやけに長い」。こうした体感の問題に向き合うとき、いちばんやってはいけないのは、勘で「たぶんあのサービスのせいだろう」と決めつけて設定をいじることだ。
原因を推測する前に、まず計測する。これが鉄則である。
幸い、systemd を採用した環境には、起動にかかった時間を段階ごと・サービスごとに数字で示してくれる systemd-analyze という専用のツールが標準で備わっている。
どこで時間を食っているのかが客観的な数字で見えれば、無効化すべきサービスや見直すべき設定の判断が、思い込みではなく根拠に基づいて下せるようになる。
📐 どの局面が時間を食っているか
まず引数なしで systemd-analyze と打つと、起動全体にかかった時間が段階別に要約されて表示される。
出力は「Startup finished in 3.2s (firmware) + 5.1s (loader) + 4.8s (kernel) + 12.3s (userspace) = 25.4s」のような形になり、ファームウェア・ブートローダ(loader)・カーネル・ユーザ空間(userspace)のそれぞれが何秒かかったかが一目で分かる。
ここでいうユーザ空間の時間は、init である systemd が動き始めてから、既定の target(graphical.target など)に到達して「起動完了」とみなされるまでの時間を指す。
一番大事なのは、この4区分のうちどこが支配的かをまず見ることだ。userspace が突出して長ければ、原因はsystemdが管理するサービス群にある可能性が高く、次に挙げる blame で深掘りする価値がある。
逆に firmware や loader が長い場合は、systemd の設定をいくらいじっても改善しない。そこはBIOS/UEFIやGRUBの領分だからだ。この切り分けが、すべての最初の分岐点になる。
📋 どのサービスが起動を待たせているか
userspace に原因がありそうだと分かったら、systemd-analyze blame の出番だ。このサブコマンドは、起動時に各サービス(unit)の初期化にかかった時間を、長い順に降順で一覧してくれる。
出力は「8.4s NetworkManager-wait-online.service」「3.1s dnf-makecache.service」のように、所要時間とサービス名が並ぶ形だ。リストの上の方に来ているサービスが、起動を待たせている主犯候補ということになる。
ここでよく見つかる典型例が NetworkManager-wait-online.service だ。これはネットワークが完全に接続されるまで起動を待つサービスのため、環境によっては数秒〜十数秒を消費する。本当にその待ちが必要かを検討し、不要なら無効化する、といった判断材料になる。
ただし、上位に来たサービスを即「犯人」と決めてよいわけではない。ここに次の落とし穴がある。
🔗 所要時間が長い=全体を遅らせている、とは限らない
blame には落とし穴がある。blame は各サービスの「所要時間」を単純に長い順で並べるが、サービスは並列に起動するため、所要時間が長いからといって、それが全体の完了を遅らせているとは限らない。他のサービスと同時並行で動いていて、待ち時間に隠れているだけかもしれないからだ。
そこで使うのが systemd-analyze critical-chain だ。これは、起動が完了するまでに直列でつながった依存の連鎖――クリティカルパス――をツリー状に表示する。
各行には、そのサービスが起動し終えた時刻(@で表示)と、そのサービス自体にかかった時間(+で表示)が示され、「どのサービスの完了を待ったせいで次が遅れたのか」という因果の鎖が見える。
本当に全体を遅らせている真犯人を突き止めるには、blame の所要時間ランキングと critical-chain の依存連鎖を両方見る。これがコツだ。
🛠 犯人が分かったら手を下す
ボトルネックが分かったら、対処は前のトピックで扱った systemctl が担う。不要だと判断したサービスは systemctl disable サービス名 で自動起動を止め、効果を確かめるために再起動してから再度 systemd-analyze で測り直す、という流れになる。
サービス自体は残しつつ完全に無効化したい場合は systemctl mask、逆に消したものを戻したい場合は systemctl enable と、状況に応じて使い分ける。
なぜそのサービスに時間がかかっているのか、起動時に何が起きていたのかをもっと詳しく知りたいときは、journalctl -b でその回の起動ログを追うと、エラーや待ちの理由が見つかることがある。
たとえば何かの応答を待ってタイムアウトしている、依存先のサービスが立ち上がるのを待っている、といった事情がログから読み取れる。計測 → 特定 → 対処 → 再計測、というループで地道に詰めていくのが王道だ。
⚠ 速くしたい一心で見落とすこと
よくある誤解は、blame の一番上に出たサービスをそのまま犯人だと決めつけてしまうことだ。前述のとおり並列起動のため、所要時間が長いことと全体を遅らせることは別物で、critical-chain と突き合わせないと判断を誤る。
また、起動を速くしたい一心で必要なサービスまで無効化すると、ネットワークやログが立ち上がらないといった別の不具合を招く。速さと安定性のバランスを忘れないことが大切だ。
実務では、サーバ構築後やトラブル後に起動時間を一度測ってベースラインを記録しておく、起動が遅くなったと感じたら推測ではなくまず systemd-analyze で数字を取る、という習慣が、無駄な設定変更や事故を減らしてくれる。
平常時の数字を知っておけば、ある日とつぜん起動が倍に伸びたときに「何かが変わった」とすぐ気づけるし、対処の前後で測り比べれば、自分の変更が本当に効いたのかを客観的に判断できる。
勘ではなく数字で語る。起動時間の改善は、その姿勢が最もはっきり実を結ぶ領域のひとつだ。