Systemd起動問題の解決:よくある問題と解決策

journalctl、失敗したユニットの確認、レスキューターダーゲット、fstabの修正、依存関係の確認、initramfsのデバッグを用いてsystemdの起動問題を診断します。

Systemd起動問題の解決:よくある問題と解決策

Linuxの起動問題は、まず使い慣れたツールが使えなくなることが多いため、緊急性が高まります。SSHがダウンしたり、グラフィカルログインが表示されなかったり、コンソールが緊急モードに落ちて、実際よりも深刻に見えるメッセージが表示されたりします。systemdの起動問題では、最初に推測するのは最善の方法ではありません。起動が停止したポイントを見つけ、そこからユニットログ、マウント障害、依存関係エラー、またはカーネル初期メッセージを逆にたどります。

このガイドでは、カーネルがsystemdをPID 1として起動した後に発生する障害と、コンソールからsystemdの障害のように見えるいくつかの近隣の問題(/etc/fstabの不良エントリ、initramfsのトラブル、ブートローダーのミス)に焦点を当てます。

Systemdの起動プロセスを理解する

Systemdは「ユニット」と呼ばれるシステムを通じてLinuxの起動プロセスを管理します。これらのユニットは、サービス(.service)、マウントポイント(.mount)、デバイス(.device)、ターゲット(.target)など、さまざまなシステムリソースとサービスを記述します。ターゲットは、他のユニットをグループ化し、起動プロセス中の特定の同期ポイントまたは状態を表す特別なユニットです(例:multi-user.target(従来のランレベル3)、graphical.target(ランレベル5))。

起動プロセスは通常、以下を含みます:

  1. カーネル初期化:カーネルがハードウェアをロードして初期化します。
  2. Initramfsステージ:初期RAMファイルシステムがロードされ、ルートファイルシステムをマウントするための必須ドライバとツールが含まれます。
  3. Systemd起動:SystemdがPID 1として引き継ぎ、default.target(多くの場合multi-user.targetまたはgraphical.targetにシンボリックリンク)を起動します。
  4. ユニットアクティベーション:Systemdがユニットファイルを読み込み、依存関係を解決し、サービスとマウントを高度に並列に起動します。

起動問題はこれらのどの段階でも発生する可能性がありますが、このガイドは主にsystemdが起動した後に現れる問題に焦点を当てています。

初期トリアージ:ブートログへのアクセス

システムが正常に起動しない場合、最初で最も重要なステップはブートログにアクセスすることです。これらのログは、何が問題だったかについての手がかりを提供します。システムがグラフィカル環境や標準のTTYにすら起動しない場合は、代替方法を使用する必要があります。

1. journalctlの使用(レスキューモード/緊急モードまたはライブメディアから)

journalctlは、systemdジャーナルをクエリするためのユーティリティです。システムがレスキューモードまたは緊急モードで起動できる場合、またはライブUSB/CDを使用してディスクにアクセスしている場合、journalctlが主要なツールです。

前回のブートのログを表示するには:

journalctl -b -1

システムが起動してからのすべてのメッセージを表示するには:

journalctl -b

失敗したユニットに関連するログを表示するには:

journalctl -b -p err..emerg # エラー、クリティカル、アラート、緊急メッセージを表示
journalctl -b --since "-5min" # 現在のブートの最後の5分間のログを表示

ライブ環境を使用している場合、ログを読むためだけに完全なchrootが必要とは限りません。インストールされたシステムをマウントし、journalctlをそのシステムに向けます:

mount /dev/mapper/vg0-root /mnt
journalctl --directory=/mnt/var/log/journal -b -1

永続ジャーナルがないシステムでは、古いブートログが/var/log/journalの下に存在しない場合があります。その場合は、/var/logの下のディストリビューション固有のログを確認するか、システムが十分に健全な状態で永続ジャーナリングを有効にした後にブートを再現します。

2. dmesgの使用

dmesgはカーネルリングバッファを表示し、ブート中にカーネルからのメッセージが含まれます。これは、systemdが完全に引き継ぐ前の、ブートプロセスの非常に早い段階で発生する問題に特に役立ちます。

dmesg

3. ユニットステータスの確認

使用可能なシェル(レスキューモード、緊急モード、またはchrootを使用したライブ環境)に入ったら、すべてのsystemdユニットのステータスを確認できます。

systemctl --failed

このコマンドは、起動に失敗したすべてのユニットをリストします。特定の失敗したユニットの詳細情報については、次を使用します:

systemctl status <unit_name>.service

そして、その特定のジャーナルエントリを表示するには:

journalctl -u <unit_name>.service -b

よくあるSystemd起動問題とその解決策

1. サービス障害とユニット障害

問題:重要なサービスが起動に失敗し、システムが目的のターゲット(例:multi-user.target)に到達できなくなります。これは多くの場合、システムが緊急モードに落ちることで現れます。

症状systemctl --failedが1つ以上のユニットを「failed」状態で表示します。journalctl -u <unit_name>.serviceは、サービスが起動できなかった理由を示すエラーメッセージを明らかにします。

一般的な原因

  • 設定の誤り:設定ファイルのタイプミス、誤ったパス、欠落した依存関係。
  • ファイル/依存関係の欠落:サービスが存在しないかアクセスできないファイルやディレクトリにアクセスしようとします。
  • リソース不足:サービスがメモリやその他のリソースを過剰に割り当てようとします。
  • 権限の問題:サービスにファイルの読み取り/書き込みやコマンドの実行に必要な権限がありません。

解決策

  1. 失敗したユニットを特定systemctl --failedを使用します。
  2. ログを調査journalctl -u <unit_name>.service -bを実行して詳細なエラーメッセージを確認します。
  3. 設定を修正:サービスの設定ファイル(例:/etc/systemd/system/<unit_name>.serviceまたは/etc/内のファイル)を編集します。ExecStartWorkingDirectoryUserGroupEnvironmentディレクティブに注意してください。
  4. 依存関係を確認:すべてのWants=Requires=After=Before=ディレクティブが正しく指定されていること、および必要なサービスが有効になっていることを確認します。
  5. 再起動して再有効化:変更後、systemctl daemon-reloadを実行し、次にsystemctl start <unit_name>.servicesystemctl enable <unit_name>.serviceを試します。

:カスタムWebサービスmywebapp.serviceが、そのデータベースが利用できないために失敗します。

# ステータスを確認
systemctl status mywebapp.service

# 手がかりのためにログを確認
journalctl -u mywebapp.service -b

# ユニットファイルを編集(例:/etc/systemd/system/mywebapp.service)
# After=ディレクティブを追加/変更して、データベースが最初に起動するようにする
# 例:After=postgresql.service mysql.service

# systemdをリロードして再試行
systemctl daemon-reload
systemctl start mywebapp.service
systemctl enable mywebapp.service # 次回起動時に起動するようにする

2. ファイルシステムの問題

問題:破損したファイルシステムや/etc/fstabの誤ったエントリにより、システムが重要なパーティションをマウントできなくなり、緊急モードに陥る可能性があります。

症状fsck障害、mountエラーに関するエラーメッセージ、または「Give root password for maintenance (or type Control-D to continue)」のようなメッセージとともにシステムがemergency modeに落ちる。

一般的な原因

  • ダーティファイルシステム:不適切なシャットダウン、停電。
  • /etc/fstabの誤り:UUID/デバイスパスのタイプミス、誤ったファイルシステムタイプ、重要でないマウントに対するnoautoの欠落。
  • ハードウェア障害:ディスクの破損。

解決策

  1. 緊急モードにアクセス:プロンプトが表示されたら、rootパスワードを入力します。
  2. /etc/fstabを確認/etc/fstabを注意深く確認し、エラーがないか調べます。疑わしい行は一時的に#でコメントアウトします。
  3. fsckを慎重に実行:ファイルシステムがアンマウントされている場合、またはディストリビューションが安全であると文書化しているメンテナンスコンテキストで読み取り専用でマウントされている場合にのみ、手動でチェックして修復します。ルート以外のパーティションの場合:
    umount /dev/sdb1
    fsck -f /dev/sdb1
    
    ルートファイルシステムを修復する必要がある場合は、ライブメディアまたはレスキュー環境から起動し、そこからfsckを実行します。重要なディスクでは、最初の手段としてfsck -yを避けます。バックアップがすでにあるか、損傷を理解していない限り、プロンプトを確認します。
  4. 再起動:変更を加えるかfsckを実行した後、再起動を試みます。

3. 依存関係の競合とユニットの順序付け

問題:サービスが間違った順序で起動するか、ユニットに競合する依存関係があり、デッドロックや障害が発生します。

症状:サービスのタイムアウト、依存関係の準備ができていないためにサービスが失敗する、systemd-analyze plotが長いチェーンやサイクルを示す。

一般的な原因

  • ユニットファイルのWants=Requires=After=Before=ディレクティブの設定ミス。
  • まだ利用できないリソースを期待するユニット。

解決策

  1. ブートシーケンスを分析systemd-analyzeを使用してブートプロセスを可視化します。

    • systemd-analyze blame:起動時間でソートされたサービスを表示し、遅いユニットを強調します。
    • systemd-analyze critical-chain:全体的なブート時間に直接影響を与えるユニットのクリティカルパスを表示します。
    • systemd-analyze plot > boot.svg:ブート依存関係グラフ全体のSVG画像を生成します。複雑な問題に非常に役立ちます。
  2. ユニット依存関係を調査systemctl list-dependencies <unit_name>を使用して、ユニットが必要とするものと、それに依存するものを確認します。

  3. ユニットファイルディレクティブを調整

    • After=Before=:ユニットの順序を制御します。A.serviceAfter=B.serviceがある場合、ABに起動します(Bが起動された場合)。ほとんどの順序付けのニーズにはAfter=を使用します。
    • Wants=:弱い依存関係を表します。A.serviceB.serviceWantsする場合、Aが起動するときにBが起動されますが、Bが失敗してもAは続行します。
    • Requires=:強い依存関係を表します。A.serviceB.serviceRequiresする場合、Aが起動するときにBが引き込まれ、Bを起動できない場合Aは失敗します。Bが明示的に停止された場合、Aも停止されます。
    • Conflicts=:現在のユニットが起動された場合に特定のユニットが停止され、その逆も同様であることを保証します。
    • PartOf=:あるユニットのライフサイクルを別のユニットにリンクします(例:sliceが停止された場合、PartOfであるすべてのユニットも停止されます)。

    ヒント:ほとんどの依存関係には、デッドロックや障害の連鎖を引き起こす可能性のある密結合を避けるために、After=Wants=を常に優先します。

4. カーネルパニック / Initramfsの問題

問題:システムが非常に早い段階で起動に失敗し、多くの場合systemdが完全に引き継ぐ前に、「Kernel panic - not syncing」またはdracutinitramfsに関連するメッセージを表示します。

症状:初期のブート障害。多くの場合、スタックトレースやルートデバイスの欠落、/dev/rootが見つからないなどに関するメッセージがテキストの壁として表示されます。

一般的な原因

  • カーネルモジュールの欠落:Initramfsにルートファイルシステム(例:LVM、RAID、特定のディスクコントローラ)に必要なドライバが含まれていません。
  • カーネル/Initramfsの破損:ファイルが損傷しています。
  • 誤ったカーネルパラメータ:GRUBのroot=パラメータが間違ったデバイスを指しています。

解決策

  1. Initramfsを再構築:これは一般的な修正です。ライブ環境または別のカーネルで起動し、システムにchrootして、initramfsを再構築します。
    # Dracutの例(Fedora/RHEL/CentOS)
    dracut -f -v /boot/initramfs-$(uname -r).img $(uname -r)
    
    # mkinitcpioの例(Arch Linux)
    mkinitcpio -P
    
    # update-initramfsの例(Debian/Ubuntu)
    update-initramfs -u -k all
    
  2. GRUB設定を確認/boot/grub/grub.cfg(または再生成する場合は/etc/default/grub)で、正しいroot=パラメータとinitrdパスを確認します。
  3. カーネルパラメータ:特定のモジュールが欠落しているか問題を引き起こしていると思われる場合、GRUBでカーネルパラメータを追加してみることができます(例:デバッグのためにinitramfsシェルにドロップするrd.break)。

5. GRUB/ブートローダーの問題

問題:システムがカーネルがロードされるポイントにすら到達しないか、GRUBメニューでスタックします。

症状:「No boot device found」、GRUBレスキュープロンプト、またはGRUBがカーネルのロードに失敗する。

一般的な原因

  • ブートローダーの破損。
  • 存在しないカーネル/initramfsを指す誤ったGRUB設定。
  • BIOS/UEFI設定が適切なブート順序を妨げている。

解決策

  1. GRUBを再インストール:ライブUSBから起動し、システムにchrootして、MBR/EFIパーティションにGRUBを再インストールします。
    # 例
    mount /dev/sdaX /mnt # ルートパーティションをマウント
    
    mount /dev/sdaY /mnt/boot/efi # 別のEFIパーティションの場合
    
    for i in /dev /dev/pts /proc /sys /run; do mount --bind $i /mnt$i; done
    chroot /mnt
    
    grub-install /dev/sda # メインディスクにインストール
    
    grub-mkconfig -o /boot/grub/grub.cfg # GRUB設定を再生成
    
    exit
    umount -R /mnt
    reboot
    
  2. BIOS/UEFI設定を確認:正しいブートドライブが優先されていることを確認します。

高度なトラブルシューティングテクニック

レスキューモード/緊急モードで起動する

これらのモードは、トラブルシューティングのための最小限の環境を提供します。これらに入るには:

  1. GRUB中eを押してカーネルコマンドラインを編集します。
  2. linux行を見つけるlinux(またはlinuxefi)で始まる行を見つけます。
  3. systemd.unit=rescue.targetを追加:レスキューモードの場合(ほとんどのサービスはオフ、シングルユーザーシェル)。
  4. systemd.unit=emergency.targetを追加:緊急モードの場合(最小限のサービス、多くの場合読み取り専用ルート)。
  5. Ctrl+XまたはF10を押して起動します。

Initramfsデバッグのためのrd.breakの使用

GRUBのカーネルコマンドラインにrd.breakを追加すると、実際のルートファイルシステムがマウントされる前に、initramfs内のシェルにドロップされます。これは、欠落したドライバやLVM/RAIDセットアップの問題など、initramfsの問題をデバッグするのに非常に役立ちます。

initramfsシェルに入ると、次のことができます:

  • lsblkmountを調査。
  • /sysrootに欠落したファイルがないか確認。
  • ルートファイルシステムを手動でマウントしてみる。

ブートパフォーマンスの分析

厳密には「障害」ではありませんが、起動時間が遅いと、根本的な問題や非効率的なサービス設定を示している可能性があります。

  • systemd-analyze blame:起動に最も時間がかかるサービスを特定します。
  • systemd-analyze critical-chain:全体的なブート時間に影響を与える依存関係のクリティカルパスを理解します。

安全なリカバリシーケンス

コンソールにいてマシンが半分起動している場合は、リカバリシーケンスを退屈に保ちます:

  1. 可能であれば、画面上の正確なエラーをキャプチャします。
  2. systemctl --failedを実行します。
  3. journalctl -b -p err..alert --no-pagerを読みます。
  4. ユニットが失敗した場合、journalctl -u unit-name -bを読みます。
  5. マウントが失敗した場合、/etc/fstabを調査し、blkidでUUIDを確認し、疑わしい重要でないマウントのみをコメントアウトします。
  6. ルートファイルシステムまたはinitramfsが関係している場合は、侵襲的な修復を行う前にライブメディアまたはレスキューモードに切り替えます。
  7. ユニットファイルを編集した後、systemctl daemon-reloadを実行し、可能な場合は影響を受けるユニットのみを再起動します。

ほとんどのsystemd起動問題は、一度に多くのことを変更しても修正されません。不良なマウント行、欠落したディスク、壊れたExecStart=を持つサービス、または順序付けのミスは、かなり直接的な痕跡を残します。その痕跡をたどり、1つの小さな修復を行い、現在のシェルで修正をテストできない場合にのみ再起動します。

これらのツールを使用してボトルネックを特定し、After=Requires=TimeoutStartSec=、またはType=ディレクティブを調整してユニットの起動を最適化します。

予防とベストプラクティス

  • 変更をテスト:ユニットファイルの変更を本番環境にデプロイする前に、ステージング環境でテストします。
  • 設定をバックアップ/etc/、または少なくとも重要な/etc/systemd/system/ファイルを定期的にバックアップします。
  • ユニットディレクティブを理解systemd.service(5)およびsystemd.unit(5)のマニュアルページをしっかりと理解することは非常に価値があります。
  • ドロップインファイルを使用/lib/systemd/system/ユニットファイルを直接変更する代わりに(更新で上書きされる可能性があります)、カスタム設定にはドロップインファイル(/etc/systemd/system/<unit_name>.service.d/*.conf)を使用します。
  • カーネルを保持:新しいカーネルが問題を引き起こした場合に備えて、システムに少なくとも1つの既知の正常な古いカーネルを常に保持します。

結論

Systemdの起動問題を解決するには、効果的なログ分析から始まる体系的なアプローチが必要です。systemdのユニットベースのアーキテクチャを理解し、journalctlsystemctlsystemd-analyzeなどのツールを活用することで、設定ミスのあるサービス、ファイルシステムの問題、複雑な依存関係の競合など、起動障害の根本原因を効率的に特定できます。レスキューまたは緊急モードで起動する機能と、高度なデバッグテクニックを組み合わせることで、システムが完全に応答しないように見える場合でも、システムを制御できるようになります。これらの戦略とベストプラクティスにより、ほとんどのsystemd起動の課題に取り組み、安定した信頼性の高いLinux運用を維持するための準備が整います。