Linux 講座 / 障害を再現して証拠に基づいて復旧する総合実習

障害復旧演習は、別の環境で正常状態をまず検証した後、原因を一つだけ変更して、観察した証拠に従って復元する方式で進めます。サービスの実行状態と実際のユーザー応答を合わせて確認することで、復旧完了を判断できます。

演習前にVMスナップショットとコンソール復旧を準備し、ログで原因を絞る手順に従って、変更前後の証拠を比較してください。

システム設定実習の基準は Ubuntu 26.04 LTS と Rocky Linux 9 系の一般インストール VM です。コンテナ・WSL・別のリリースでは、サービスやパッケージの構成が異なる場合があります。仮想マシン実習環境の作成で、コンソールの復旧とバージョン確認を最初に準備してください。

演習範囲と正常基準を準備する

systemdのユーザーマネージャーを利用でき、Python 3とcurlがインストールされたUbuntu・Rocky Linuxの演習VMを使用します。運用Nginx・SSH・ファイアウォール・ディスクは変更しません。ループバック18080ポートが空いているかss -lntで確認し、すでに使用中の場合は、この演習のすべてのポート番号を他の空いている番号に変更します。

以下の例は /usr/bin/python3 を使用しているため、まず command -v python3 で実際のパスを確認してください。別のパスを使う場合は、ExecStartと実験1の置換パターンも同じパスに合わせて変更します。既存の linux-course-recovery.service や ~/linux-recovery-lab があれば上書きせず、新しい名前を選んでください。Python の 簡易 HTTP サーバー はこのローカル実習のみに使用し、インターネット運用サーバーとして公開しないでください。

mkdir -p "$HOME/linux-recovery-lab/site" "$HOME/.config/systemd/user"
printf "recovery baseline\n" > "$HOME/linux-recovery-lab/site/index.html"
cat > "$HOME/.config/systemd/user/linux-course-recovery.service" <<'EOF'
[Unit]
Description=Isolated Linux recovery lab

[Service]
Type=simple
WorkingDirectory=%h/linux-recovery-lab/site
ExecStart=/usr/bin/python3 -m http.server 18080 --bind 127.0.0.1
EOF
systemctl --user daemon-reload
systemctl --user start linux-course-recovery.service
systemctl --user is-active linux-course-recovery.service
curl --fail --max-time 5 http://127.0.0.1:18080/
cp "$HOME/.config/systemd/user/linux-course-recovery.service" "$HOME/linux-recovery-lab/service.good"

active と recovery baseline の応答を確認した後にのみ障害を作ります。正常なユニットファイルは service.good に保存しており、サービスは有効化していないため、起動時の自動開始も追加していません。正常な状態が成立しない場合は、まず Python のパス・ユニットの構文・ポートの衝突から解決してください。

実験 1: 間違った実行パスでの失敗再現

sed -i 's@ExecStart=/usr/bin/python3 @ExecStart=/nonexistent/course-python @' "$HOME/.config/systemd/user/linux-course-recovery.service"
systemctl --user daemon-reload
systemctl --user restart linux-course-recovery.service
systemctl --user status linux-course-recovery.service --no-pager
journalctl --user -u linux-course-recovery.service --since "5 minutes ago" --no-pager

ユニットは存在しない実行ファイルを指しているため、アクティブ状態を維持できません。タイミングによっては開始コマンドやその後のステータスで失敗を確認できます。ジャーナルで実行失敗と 203/EXEC のような状態を探し、実際のメッセージを記録してください。サービスの失敗をすべてネットワーク問題と判断しないでください。

正常設定を復元して応答まで再検証する

cp "$HOME/linux-recovery-lab/service.good" "$HOME/.config/systemd/user/linux-course-recovery.service"
systemctl --user daemon-reload
systemctl --user reset-failed linux-course-recovery.service
systemctl --user start linux-course-recovery.service
systemctl --user is-active linux-course-recovery.service
curl --fail --max-time 5 http://127.0.0.1:18080/

正常ファイルを戻し、systemdに再読込させた後、サービスを開始します。reset-failedは失敗記録と起動制限カウンターを初期化できますが、設定自体の誤りを修正するコマンドではありません。状態と実際のページがすべて戻れば、今回の実験の復旧は終了です。

実験2: ポートが閉じている場合とHTTPエラーを比較する

curl -i --max-time 5 http://127.0.0.1:18080/missing-resource
systemctl --user stop linux-course-recovery.service
curl -i --connect-timeout 2 --max-time 5 http://127.0.0.1:18080/
ss -lnt
systemctl --user start linux-course-recovery.service
curl --fail --max-time 5 http://127.0.0.1:18080/

最初のリクエストは、稼働中のサーバーが、存在しないリソースの要求にHTTP 404を返す場合です。サービス停止後のリクエストは、接続拒否などの接続段階での失敗で、正常なHTTP 404応答とは異なります。curlに--failを付けなければ、404を受け取っても終了ステータスは0になる可能性がある点も比較してください。リモートファイアウォールを切らずに、サービス・接続・HTTPの失敗を区別する練習です。

一度に一つの条件だけを変えて記録する

記録項目 この実習で残す内容
正常基準 active·待ち受けポート·予想ページ
変更 ExecStart パスまたはサービス停止 ひとつ
証拠 時間·終了状態·ジャーナル·HTTP·ソケット
復旧 正常ファイル復元またはサービス開始
再検証 同一 URL・ポート・レスポンス本文
再発防止 配布前の構文・パスチェックと状態確認

ディスクをいっぱいにする、SSH をブロックする、ランダムなファイルを削除するなど、実際の復旧経路まで失う可能性のある実験はこの段階では行いません。そのような実験は、別の複製 VM・制限付き仮想ディスク・検証済みコンソールとバックアップのある環境で範囲を定めて行う必要があります。目的は障害を大きくすることではなく、観察から復旧までの判断過程を習得することです。

実習サービスを停止して作成したファイルだけを整理する

systemctl --user stop linux-course-recovery.service
systemctl --user reset-failed linux-course-recovery.service
rm -- "$HOME/.config/systemd/user/linux-course-recovery.service"
systemctl --user daemon-reload
ss -lnt

ループバック 18080の待ち受けが消えたか確認します。作業フォルダには正常設定のバックアップと静的ファイルだけが残っているので、内容を確認した後、ファイルマネージャで整理できます。失敗状態の整理も該当の実習ユニットにのみ適用し、他のユーザーサービスの記録は保持します。

公式ドキュメント