本記事には広告(アフィリエイトリンク)が含まれます。

Linux障害対応 総合演習3シナリオ

Linuxエンジニア養成講座 第36回(最終回)|全36回・フェーズ4「サーバー構築と運用」の最終回(9/9回目)です。
前回: 第35回で Ansible の基本を習得し、ad-hoc コマンドと playbook による構成管理の自動化を実践しました。
今回学ぶこと: 意図的に壊した環境を自力で直す総合演習を通じて、35回分の知識を総動員します。

前回の予告で「意図的に壊した環境を直す演習を通じて、これまで35回で学んだ知識を総動員します。CPU・メモリ・ディスクI/O・ネットワークの4リソース確認を鉄則として身につけます」とお伝えしました。Ansible で「構成を自動で適用する」方法を学びました。しかし、自動化しても障害は起きます。設定ミス、リソース枯渇、想定外の負荷。そのとき頼れるのは、35回で積み上げてきた「調べて、読んで、判断する力」です。

この記事を読み終えると、以下のことができるようになります。

  • 障害発生時に4リソース(CPU・メモリ・ディスクI/O・ネットワーク)の初動確認を迷わず実行できる
  • ログとエラーメッセージから原因を論理的に辿れる
  • 手がかりが少ない状況でも切り分け思考で障害箇所を絞り込める
  • 障害の第一報・完了報告書を業務品質で作成できる
  • 修復後の動作確認、変更の Git 記録、再発防止策の策定まで一連のサイクルを完遂できる

この回は通常の記事より分量が多くなっています。3つのシナリオに分かれているので、1日1シナリオのペースで進めても構いません。各シナリオの間でスナップショットに復元するため、途中で中断しても問題ありません。

なぜトラブルシューティング力が必要か

1つ考えてみてください。サーバーの構築には何日かかるでしょうか。手順書があれば、数日で終わります。では、そのサーバーは何年動き続けるでしょうか。3年、5年、場合によっては10年以上です。

構築は手順書に沿って進められます。しかし障害は手順書にない状況で発生します。深夜3時にアラートが鳴り、画面には見たことのないエラーメッセージが表示されている。手順書に「このエラーが出たら」とは書いてありません。そのとき必要なのは、暗記した手順ではなく「何を調べればいいか」を判断する力です。

新人が障害対応で直面する壁は、大きく3つあります。

  • 何を見ればいいかわからない: サーバーが応答しない。でもどこから手をつければいいのか。→ 4リソース確認で解決します(シナリオ1で体験)
  • エラーメッセージが読めない: ログに英語のエラーが大量に出ている。どれが原因でどれが結果なのか。→ ログの読み方で解決します(シナリオ2で体験)
  • 手がかりが少ない: 「なんか遅い」としか情報がない。エラーも出ていないように見える。→ 切り分け思考で解決します(シナリオ3で体験)

今日の演習では、この3つの壁を順番に乗り越えていきます。

4リソース確認の鉄則

障害対応で最も危険なのは「思い込み」です。「Webが見えないならApacheが落ちたんだろう」「遅いならメモリが足りないんだろう」。原因を決めつけてしまうと、本当の原因を見落とします。

なぜ4リソースすべてを確認するのか、考えてみてください。障害の原因が1つだけとは限りません。ディスクの逼迫がログの書き込み失敗を引き起こし、ログの書き込み失敗がサービスの停止を引き起こす。1つの根本原因から複数の症状が連鎖的に発生します。表面に見える症状だけを直しても、根本原因が残っていればまた同じ障害が発生します。だからこそ、特定の症状に飛びつく前に全体像を把握する必要があるのです。

初動5コマンド(最初の30秒)

サーバーにログインしたら、まず以下の5つを実行します。30秒もかかりません。この5つで「どのリソースに異常があるか」の全体像が見えます。

確認対象コマンド何がわかるか
CPU・負荷uptimeロードアベレージ(1分/5分/15分)。CPUコア数を超えていたら高負荷
メモリfree -h物理メモリとスワップの使用状況。available が極端に少なければ危険
ディスクdf -h各パーティションの使用率。90%超は要対処
サービスsystemctl --failed起動に失敗したサービスの一覧。正常なら「0 loaded units listed」
ネットワークip addr + pingNICの状態と疎通。IPが付いているか、外部と通信できるか

深堀りコマンド(リソース別)

初動5コマンドで異常が見つかったら、該当するリソースを深堀りします。

リソース深堀りコマンド用途
CPUps aux --sort=-%cpu | headCPU消費の多いプロセスを特定
CPUtop -bn1 | head -20リアルタイムの負荷状況をスナップショットで取得
メモリps aux --sort=-%mem | headメモリ消費の多いプロセスを特定
ディスクdu -sh /var/* | sort -rh | headどのディレクトリが容量を使っているか特定
ディスクlsof +D /var/log特定ディレクトリを開いているプロセスを特定
ネットワークss -tlnpリッスンしているポートとプロセスの対応
ネットワークfirewall-cmd --list-all許可されているサービス・ポートの確認
ログjournalctl -u サービス名 --no-pager -n 50特定サービスの最新ログ50行
ログjournalctl -p err --since "1 hour ago"直近1時間のエラーレベル以上のログ

これらのコマンドはすべて、この講座の中で登場したものです。第12回の ps、第6回の df と du、第23回の journalctl、第20回の firewall-cmd。個別に覚えたコマンドを「障害対応」という文脈でつなげて使います。

演習の進め方

SP7 からの復元

まず、前回の末尾で取得した SP7 スナップショットから全VMを復元します。

ホストPCで実行:

PS> Restore-VMSnapshot -Name "SP7_pre-troubleshoot" -VMName alma-main -Confirm:$false
PS> Restore-VMSnapshot -Name "SP7_pre-troubleshoot" -VMName alma-sub -Confirm:$false
PS> Restore-VMSnapshot -Name "SP7_pre-troubleshoot" -VMName alma-proxy -Confirm:$false
PS> Start-VM -Name alma-main, alma-sub, alma-proxy

SP7 の状態

SP7 には、これまでの講座で構築してきた以下の状態が含まれています。

  • httpd第29回): 起動済み・自動起動有効。/var/www/html/index.html が配置済み
  • mariadb第30回): 起動済み・自動起動有効。sampledb データベース、appuser ユーザー作成済み
  • /data パーティション第25回): LVM で作成した 5GB の領域。vg_data に 5GB の空きあり
  • firewalld第20回): http / https サービスを許可済み
  • SELinux: Enforcing
  • Git第34回): /etc 配下で初期化済み

各シナリオの流れ

3つのシナリオすべて、以下の流れで進めます。これは実際の障害対応と同じサイクルです。

  1. script 開始: 作業ログの記録を開始する(第2回
  2. 第一報: 状況を報告する(事実と推測を分ける)
  3. 初動確認: 4リソース + サービス状態を確認する
  4. 切り分け・原因特定: 異常箇所を深堀りし、根本原因を突き止める
  5. 修復: 原因に対処する
  6. 動作確認: 修復が正しく行われたことを確認する
  7. 完了報告書: 原因・対応内容・再発防止策を記録する
  8. Git 記録: 設定変更があればコミットする
  9. script 終了

各シナリオ終了後は SP7 に復元してから次のシナリオに進んでください。所要時間の目安は、シナリオ1が約60分、シナリオ2が約45分、シナリオ3が約45分です。

15分ルール

実務の障害対応では「15分調べてわからなければエスカレーション(上位者への報告・相談)」が目安です。今回は演習なのでヒントを用意していますが、実務では1人で抱え込まないことが鉄則です。15分経っても手がかりがなければ、自分の調査結果(「ここまでは確認した」「ここから先がわからない」)を添えて先輩に相談してください。「何もわかりません」ではなく「ここまでは調べました」と伝えることで、先輩の助けを引き出せます。

シナリオ1: Webサイトにアクセスできない

難易度: ガイド付き(手順を示しながら進めます)

使う知識: 第2回(報連相)、第4回(環境確認)、第6回(df/du)、第8回(grep/パイプ)、第12回(プロセス管理)、第13回(systemd)、第15回(初動コマンド集)、第20回(firewalld)、第25回(LVM)、第29回(Apache)、第34回(Git)

状況

監視システムから alma-main の HTTP 応答なしアラートが来ました。あなたが一次対応担当です。

障害を発生させる

以下のコマンドで意図的に環境を壊します。3つの問題を同時に仕込みます。

alma-mainで実行:

$ sudo fallocate -l 4500M /data/bigfile.dat
$ sudo systemctl stop httpd
$ sudo firewall-cmd --remove-service=http --permanent
$ sudo firewall-cmd --remove-service=https --permanent
$ sudo firewall-cmd --reload

実行したら、これらのコマンドのことは一度忘れてください。ここからは「何が起きているかわからない」状態で調査を始めます。

ステップ1: script 開始

障害対応を始める前に、作業ログの記録を開始します。第2回で学んだ script コマンドです。

alma-mainで実行:

$ script ~/troubleshoot_s1.log

ステップ2: 第一報を作成する

第2回で学んだ第一報テンプレートに沿って、現時点でわかっている情報を報告します。原因がわかるまで待つ必要はありません。

模範例:

【障害発生】alma-main HTTP応答なし
■ 事象: 監視システムにてalma-mainのHTTP応答なしアラートを検知
■ 検知: 2026/04/05 09:30 監視アラート
■ 影響: Webサイトへの外部アクセス不可(確認中)
■ 状況: 原因調査を開始(対応者: 自分の名前)
■ 次回報告: 10:00 または状況変化時

ステップ3: 初動5コマンド

思い込みを排除するために、4リソースすべてを確認します。

alma-mainで実行:

$ uptime

実行結果:

 09:20:42 up  2:38,  1 user,  load average: 0.02, 0.03, 0.00

ロードアベレージは 0.02 です。CPU に異常はありません。

alma-mainで実行:

$ free -h

実行結果:

               total        used        free      shared  buff/cache   available
Mem:           3.8Gi       669Mi       2.7Gi        12Mi       714Mi       3.2Gi
Swap:          3.9Gi          0B       3.9Gi

available が 3.2GB あります。メモリに異常はありません。

alma-mainで実行:

$ df -h

実行結果(抜粋):

ファイルシス                   サイズ  使用  残り 使用% マウント位置
/dev/mapper/almalinux-root        64G  2.6G   62G    5% /
/dev/mapper/vg_data-lv_data      5.0G  4.5G  488M   91% /data

/data が91%。これは異常です。正常時は2%でした。何かが大量の容量を使っています。メモして次に進みます。

alma-mainで実行:

$ systemctl --failed

実行結果:

0 loaded units listed.

失敗したサービスはありません。ただし、httpd が「停止しているが failed ではない(inactive)」という状態は、ここでは見えません。systemctl --failed は「起動しようとして失敗した」サービスだけを表示します。「そもそも停止している」サービスは別途確認が必要です。

alma-mainで実行:

$ ping -c 1 10.0.1.3

実行結果:

PING 10.0.1.3 (10.0.1.3) 56(84) bytes of data.
64 バイト応答 送信元 10.0.1.3: icmp_seq=1 ttl=64 時間=0.469ミリ秒

--- 10.0.1.3 ping 統計 ---
送信パケット数 1, 受信パケット数 1, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.469/0.469/0.469/0.000 ms

ネットワーク疎通は正常です。

初動5コマンドのまとめ: CPU 正常、メモリ 正常、ディスク /data 異常(91%)、失敗サービスなし、ネットワーク正常。

ステップ4: httpd の状態確認

アラートは「HTTP応答なし」でした。httpd の状態を直接確認します。

alma-mainで実行:

$ systemctl status httpd

実行結果(抜粋):

● httpd.service - The Apache HTTP Server
     Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; preset: disabled)
     Active: inactive (dead) since ...

inactive (dead) です。httpd は停止しています。enabled なので自動起動設定はあるのに、現在は動いていません。

ステップ5: httpd を起動する

alma-mainで実行:

$ sudo systemctl start httpd

起動できました。localhost で HTTP 応答が返るか確認します。

alma-mainで実行:

$ curl http://localhost

実行結果:

<h1>Hello from alma-main</h1>

localhost からは応答が返りました。しかし、監視アラートは「外部からアクセスできない」という報告でした。外部から確認してみます。

alma-subで実行(alma-main に SSH してから alma-sub に接続、または別ターミナル):

$ curl http://10.0.1.1

実行結果:

curl: (7) Failed to connect to 10.0.1.1 port 80: ホストへの経路がありません

localhost からは応答するのに、外部からは接続拒否。httpd 自体は動いている。ここで「httpd と外部クライアントの間に何があるか」を考えてください。

ステップ6: firewalld の確認

第20回で学んだ通り、httpd がリッスンしていても、firewalld がポート80を許可していなければ外部からの接続は拒否されます。localhost(loopback)は trusted zone で処理されるため影響を受けませんが、外部からの通信は public zone のルールが適用されます。

alma-mainで実行:

$ sudo firewall-cmd --list-all

実行結果(抜粋):

public (active)
  target: default
  services: cockpit dhcpv6-client ssh

services に http と https がありません。firewalld が外部からのHTTP通信をブロックしています。

alma-mainで実行:

$ sudo firewall-cmd --add-service=http --permanent
$ sudo firewall-cmd --add-service=https --permanent
$ sudo firewall-cmd --reload

alma-sub から再度確認します。

alma-subで実行:

$ curl http://10.0.1.1

実行結果:

<h1>Hello from alma-main</h1>

外部からもHTTP応答が返りました。httpd の問題は解決です。

ステップ7: /data の異常対処

初動5コマンドで見つけた /data の使用率91%をそのままにしてはいけません。何がディスクを圧迫しているか調べます。

alma-mainで実行:

$ du -sh /data/*

実行結果:

4.4G	/data/bigfile.dat

4.4GB の巨大ファイルが見つかりました。このファイルが何なのか(業務で必要なデータなのか不要なのか)を判断します。今回は演習用に作成した不要ファイルなので削除します。

alma-mainで実行:

$ sudo rm /data/bigfile.dat
$ df -h /data

実行結果:

ファイルシス                   サイズ  使用  残り 使用% マウント位置
/dev/mapper/vg_data-lv_data      5.0G   68M  5.0G    2% /data

使用率が2%に戻りました。しかし、5GB しかない領域は今後も逼迫するリスクがあります。第25回で学んだ LVM の拡張で、再発防止策を講じましょう。

alma-mainで実行:

$ sudo lvextend -L +2G /dev/vg_data/lv_data

実行結果:

  Size of logical volume vg_data/lv_data changed from 5.00 GiB (1280 extents) to 7.00 GiB (1792 extents).
  Logical volume vg_data/lv_data successfully resized.

第25回で学んだ通り、LV を拡張しただけではファイルシステムは広がりません。xfs_growfs でファイルシステムも拡張します。

alma-mainで実行:

$ sudo xfs_growfs /data

alma-mainで実行:

$ df -h /data

実行結果:

ファイルシス                   サイズ  使用  残り 使用% マウント位置
/dev/mapper/vg_data-lv_data      7.0G   76M  7.0G    2% /data

7GB に拡張されました。

ステップ8: 完了報告書

すべての問題を修復し動作確認が終わったら、完了報告書を作成します。

【障害完了報告】alma-main HTTP応答なし

■ 発生日時: 2026/04/05 09:30
■ 復旧日時: 2026/04/05 10:15
■ 影響範囲: alma-mainのWebサイトへのアクセス不可

■ 根本原因:
  1. httpd サービスが停止していた
  2. firewalld から http/https サービスが削除されていた
  3. /data パーティションの使用率が91%に達していた(4.4GBの不要ファイル)

■ 対応内容:
  1. httpd を起動(systemctl start httpd)
  2. firewalld に http/https を再追加(--permanent + --reload)
  3. /data/bigfile.dat(4.4GB)を削除
  4. /data を 5GB → 7GB に LVM 拡張(再発防止)

■ 動作確認:
  - curl http://localhost → 正常応答確認(localhost)
  - alma-sub から curl http://10.0.1.1 → 正常応答確認(外部)
  - firewall-cmd --list-all → http/https 表示確認
  - df -h /data → 7GB / 使用率2% 確認

■ 再発防止策:
  - /data の使用率を監視対象に追加する(閾値: 80%)
  - httpd の停止原因を調査する(ログに停止理由がないか確認)

■ 対応者: (自分の名前)

ステップ9: Git 記録

firewalld の設定を変更したので、第34回で学んだ Git で変更を記録します。

alma-mainで実行:

$ cd /etc
$ sudo git add firewalld/
$ sudo git commit -m "restore http/https services after incident S1"

alma-mainで実行:

$ exit

exit で script を終了します。作業ログは ~/troubleshoot_s1.log に保存されています。

ここで休憩できます: シナリオ1はここで完了です。次のシナリオに進む前に SP7 に復元してください。今日はここまでにして、別の日にシナリオ2から再開しても構いません。

SP7 復元手順(ホストPCで実行):

PS> Restore-VMSnapshot -Name "SP7_pre-troubleshoot" -VMName alma-main -Confirm:$false
PS> Start-VM -Name alma-main

シナリオ2: データベースに接続できない

難易度: 質問形式(問いかけに答えながら進めます)

使う知識: 第2回(報連相)、第8回(grep)、第9回(vi)、第13回(systemd/journalctl)、第23回(ログ管理)、第28回(SELinux)、第30回(MariaDB)、第34回(Git)

状況

開発チームから連絡がありました。「alma-main のデータベースに接続できなくなりました。エラーは “Can’t connect to MySQL server” と出ています。」

障害を発生させる

alma-mainで実行:

$ sudo systemctl stop mariadb
$ sudo sed -i '/\[mysqld\]/a port=3307' /etc/my.cnf.d/mariadb-server.cnf

1つ目のコマンドで MariaDB を停止し、2つ目のコマンドで設定ファイルを変更します。sed 自体は成功しますが、この設定変更の結果 MariaDB が起動できなくなります(これが今回の障害です)。壊し終わったら、ここから先は「何が起きたかわからない」状態で調査を始めます。

ステップ1: script 開始と第一報

alma-mainで実行:

$ script ~/troubleshoot_s2.log

第一報を作成してください。以下のテンプレートを使います。

【障害発生】(件名を書く)
■ 事象: (何が起きているか)
■ 検知: (いつ・どうやって検知したか)
■ 影響: (誰にどんな影響があるか)
■ 状況: (現在の対応状況)
■ 次回報告: (次に報告する予定時刻)

ステップ2: まず何を確認しますか

「データベースに接続できない」と聞いて、いきなり MariaDB を調べたくなるかもしれません。しかし、まずは4リソースの初動確認です。

alma-mainで実行:

$ uptime
$ free -h
$ df -h
$ systemctl --failed
$ ping -c 1 10.0.1.3

CPU 正常、メモリ 正常、ディスク 正常、ネットワーク 正常。systemctl --failed にも何も出ません。MariaDB は手動で停止された状態(inactive)のため、--failed には表示されません。4リソースに明らかな異常はないようです。

ステップ3: 開発チームのエラーから何がわかりますか

「Can’t connect to MySQL server」というエラーは、MariaDB への接続自体ができないことを示しています。MariaDB が動いているか確認します。

alma-mainで実行:

$ systemctl status mariadb

実行結果(抜粋):

○ mariadb.service - MariaDB 10.5 database server
     Loaded: loaded (/usr/lib/systemd/system/mariadb.service; enabled; preset: disabled)
     Active: inactive (dead) since ...

inactive (dead) です。MariaDB が停止しています。起動を試みます。

alma-mainで実行:

$ sudo systemctl start mariadb

起動に失敗します。systemctl status mariadb を再度確認すると failed になっています。さきほど systemctl --failed に何も出なかったのに、ここで初めて failed が現れました。--failed は「起動に失敗したサービス」を表示するもので、手動停止(inactive)は表示されません。だからこそ「疑わしいサービスは直接 systemctl status で確認する」ことが大切です。

ステップ4: サービスが起動していません。次に何を確認しますか

サービスが failed なら、次はログです。第23回で学んだ journalctl で MariaDB のログを確認します。

alma-mainで実行:

$ journalctl -u mariadb --no-pager -n 30

ログが大量に出てきます。エラーに絞り込んでみましょう。

ステップ5: ログにエラーがあります。キーワードで絞り込んでみてください

第8回で学んだ grep でエラーを絞り込みます。

alma-mainで実行:

$ journalctl -u mariadb --no-pager | grep -i error

MariaDB は独自のログファイルも出力しています。そちらも確認します。

alma-mainで実行:

$ sudo tail -20 /var/log/mariadb/mariadb.log

実行結果(抜粋):

[ERROR] Can't start server: Bind on TCP/IP port. Got error: 13: Permission denied
[ERROR] Do you already have another mysqld server running on port: 3307 ?
[ERROR] Aborting

3つの重要な手がかりが見つかりました。

  • Bind on TCP/IP port: ポートへの接続(バインド)で失敗した
  • error: 13: Permission denied: 権限が拒否された
  • port: 3307: 対象のポートは 3307

ステップ6: Permission denied でポート 3307。原因は何でしょうか

MariaDB の標準ポートは 3306 です。それが 3307 になっている。まず設定ファイルを確認します。

alma-mainで実行:

$ grep port /etc/my.cnf.d/mariadb-server.cnf

実行結果:

port=3307

設定ファイルに port=3307 が追加されています。MariaDB は 3307 番ポートで起動しようとしています。

では、なぜ Permission denied なのでしょうか。ポート 3307 でリッスンする権限がない。第28回で学んだことを思い出してください。

SELinux です。SELinux は、各サービスがどのポートを使用してよいかをポリシーで管理しています。

alma-mainで実行:

$ sudo semanage port -l | grep mysqld

実行結果:

mysqld_port_t                  tcp      1186, 3306, 63132-63164

3307 がありません。SELinux のポリシーでは、MariaDB(mysqld)は 3306 番ポートを使用することが許可されていますが、3307 は許可されていません。だから Permission denied が発生しました。

ステップ7: 修復する

ここには2つの修復方法があります。

方法A: 設定を元に戻す(推奨)

ポートを変更する理由がないなら、設定を元に戻すのが最もシンプルです。

alma-mainで実行:

$ sudo vi /etc/my.cnf.d/mariadb-server.cnf

第9回で学んだ vi で port=3307 の行を削除します。その行にカーソルを合わせて dd で行削除し、:wq で保存します。

alma-mainで実行:

$ sudo systemctl start mariadb

方法B: SELinux にポートを許可する

業務要件でポート 3307 を使う必要がある場合は、SELinux のポリシーにポートを追加します。

alma-mainで実行:

$ sudo semanage port -a -t mysqld_port_t -p tcp 3307
$ sudo systemctl start mariadb

どちらの方法を選んでも構いません。今回は方法Aで進めます。

ステップ8: 動作確認

alma-mainで実行:

$ systemctl status mariadb

実行結果(抜粋):

     Active: active (running) since ...

起動しました。データベースに接続できるか確認します。

alma-mainで実行:

$ mysql -u appuser -pAppPass456 -e 'SHOW DATABASES;'

実行結果:

Database
information_schema
sampledb

sampledb が表示されました。開発チームに「復旧しました。接続を確認してください」と連絡します。

ステップ9: 完了報告書と Git 記録

以下のテンプレートに沿って、完了報告書を自分で作成してください。シナリオ1の模範例を参考にします。

【障害完了報告】(件名を書く)

■ 発生日時:
■ 復旧日時:
■ 影響範囲:

■ 根本原因:

■ 対応内容:

■ 動作確認:

■ 再発防止策:

■ 対応者:

設定ファイルを変更した場合は Git で記録します。

alma-mainで実行:

$ cd /etc
$ sudo git add my.cnf.d/
$ sudo git commit -m "restore mariadb default port after incident S2"

alma-mainで実行:

$ exit

script 終了です。

ここで休憩できます: シナリオ2はここで完了です。次のシナリオに進む前に SP7 に復元してください。

SP7 復元手順(ホストPCで実行):

PS> Restore-VMSnapshot -Name "SP7_pre-troubleshoot" -VMName alma-main -Confirm:$false
PS> Start-VM -Name alma-main

シナリオ3: サーバーが遅い

難易度: ほぼ自力(ヒントは隠してあります)

使う知識: 第2回(報連相)、第8回(grep/パイプ)、第12回(プロセス管理)、第13回(systemd)、第15回(初動コマンド集)、第24回(cron)、第34回(Git)

状況

先輩から Slack で連絡がありました。「alma-main が何か遅いんだけど、ちょっと見てくれない? 特にエラーは出てないと思うんだけど。」

シナリオ1・2とは異なり、エラーメッセージもアラートもありません。「何か遅い」だけ。こういう曖昧な報告が実務では最も多く、最も難しい障害です。

障害を発生させる

alma-mainで実行:

$ cat > /tmp/runaway.sh << 'SCRIPT'
#!/bin/bash
while true; do
    echo "$(date) Processing batch job..." >> /tmp/batch_output.log
    for i in $(seq 1 10000); do
        echo $i > /dev/null
    done
done
SCRIPT
$ chmod +x /tmp/runaway.sh
$ (crontab -l 2>/dev/null; echo '* * * * * /tmp/runaway.sh') | crontab -
$ nohup /tmp/runaway.sh &>/dev/null &
$ nohup /tmp/runaway.sh &>/dev/null &

10秒ほど待ってから調査を始めてください。壊しコマンドの内容は忘れてください。

ステップ1: script 開始と第一報

alma-mainで実行:

$ script ~/troubleshoot_s3.log

第一報を作成してください(テンプレートはシナリオ2を参考にしてください)。

ステップ2: まず何をしますか

「遅い」の原因候補は多岐にわたります。CPU か、メモリか、ディスクか、ネットワークか。思い込みで決めつけず、まずは全体を見ます。

ヒント: 最初に実行するコマンド

初動5コマンド(uptime, free -h, df -h, systemctl –failed, ping)を実行してください。

初動5コマンドを実行すると、1つだけ異常が見つかるはずです。どのコマンドの結果が異常でしたか。

ヒント: 異常が見つかるコマンド

uptime のロードアベレージが高くなっています。alma-main は2コアなので、ロードアベレージが2.0を超えていればCPU待ちが発生しています。一方、systemctl --failed には何も表示されません。サービスはすべて正常です。これがこのシナリオの難しいところです。

ステップ3: CPU 高負荷の原因を特定する

uptime で高負荷が判明しました。次は「何が CPU を使っているか」を特定します。

ヒント: CPU 消費プロセスを調べるコマンド

第12回で学んだ ps aux --sort=-%cpu | head を実行してください。CPU 使用率の高い順にプロセスが表示されます。

alma-mainで実行:

$ ps aux --sort=-%cpu | head

実行結果(例):

USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
develop+   26263 93.5  0.1   6364  4480 ?        R    09:18   0:15 /bin/bash /tmp/runaway.sh
develop+   26299 91.1  0.1   6364  4480 ?        R    09:18   0:15 /bin/bash /tmp/runaway.sh

/tmp/runaway.sh というスクリプトが2つ動いていて、それぞれ CPU を 90% 以上使っています。

ステップ4: 暴走プロセスを停止する

ヒント: プロセスを止めるコマンド

第12回で学んだ kill コマンドです。PID は ps の結果で確認できます。複数ある場合はすべて停止してください。pkill -f runaway.sh なら名前で一括停止できます。

alma-mainで実行:

$ pkill -f runaway.sh

プロセスを止めたら、本当に止まったか確認します。

alma-mainで実行:

$ ps aux | grep runaway

grep 自身のプロセス以外に runaway.sh が表示されなければ停止できています。

ステップ5: 再発を防ぐ

プロセスを kill しただけで終わりにしていいでしょうか。1分後にまた同じプロセスが起動したら意味がありません。「なぜこのプロセスが動いていたのか」を考えてください。

ヒント: 定期的にプロセスが起動する仕組み

第24回で学んだ cron です。crontab -l で登録されたジョブを確認してください。

alma-mainで実行:

$ crontab -l

実行結果:

* * * * * /tmp/runaway.sh

* * * * * は「毎分実行」です。kill してもまた1分後に起動されます。cron 登録を削除しなければ根本解決になりません。

alma-mainで実行:

$ crontab -r

crontab -r は全エントリを削除します。他の cron ジョブが登録されている場合は crontab -e で該当行のみ削除してください。今回は他のジョブがないので -r で問題ありません。

ステップ6: 不要ファイルの削除と動作確認

暴走スクリプトが出力し続けたログファイルも残っています。

alma-mainで実行:

$ ls -lh /tmp/runaway.sh /tmp/batch_output.log

不要なので削除します。

alma-mainで実行:

$ rm /tmp/runaway.sh /tmp/batch_output.log

負荷が下がったか確認します。

alma-mainで実行:

$ uptime

ロードアベレージが低下していれば復旧です(5分平均と15分平均はしばらく高いままですが、1分平均が下がっていれば問題ありません)。

ステップ7: このシナリオで見落としやすいポイント

systemctl --failed は正常だったのに問題がありました。障害はサービスだけで起きるとは限りません。cron ジョブ、手動実行のスクリプト、別ユーザーのプロセスなど、systemd の管理外で動いているものが原因になることがあります。

完了報告書をゼロから作成してください。シナリオ1の模範例を参考にしつつ、根本原因の考察まで書きましょう。「なぜこのスクリプトが暴走したのか」「cron に誰が登録したのか」。障害を直すだけでなく、「なぜ起きたのか」を考えることが再発防止の第一歩です。

alma-mainで実行:

$ exit

script 終了です。3つのシナリオすべて完了しました。

問いかけ: この復旧を Ansible で自動化するとしたら

前回学んだ Ansible をここで振り返ります。シナリオ1の復旧手順を playbook にするとしたら、どんなタスクが必要でしょうか。コードを書く必要はありません。「何をどの順番で自動化するか」を考えてみてください。

  • 不要な巨大ファイルを削除する → file モジュールで state: absent
  • httpd サービスを起動する → service モジュールで state: started
  • firewalld に http/https を許可する → firewalld モジュール相当の設定

手動での復旧手順を知っているからこそ、自動化の設計ができます。「構築と障害対応を経験した上で自動化する」という順番が大切です。仕組みを知らずに playbook をコピーしても、障害が起きたとき自分で対処できません。

ヒヤリハット: 「動いた」と「直った」は違う

事例: 深夜2時、Webサイトが応答しなくなった。急いで Apache を再起動したら復旧した。「復旧しました」と報告して寝た。翌朝、また同じ障害が再発した。

原因: /var/log がディスク容量の100%に達していて、Apache がアクセスログを書き込めなくなっていた。Apache の再起動で一瞬は動いたが、ログが溜まるたびに同じ問題が発生する。根本原因は「ログのローテーション設定が不十分だったこと」だった。

教訓: 「サービスを再起動したら動いた」は「直った」ではありません。4リソースの確認を省略して表面的な症状だけ解消すると、根本原因が残ったまま次の障害を待つことになります。

やってみよう: 自分で壊して自分で直す

3シナリオを終えたら、SP7 に復元してから以下の壊しメニューに挑戦してみてください。1つ以上を選んで実施します。

課題1: SSH 接続不可にして復旧する

alma-mainで実行:

$ sudo sed -i 's/^#ListenAddress 0.0.0.0/ListenAddress 127.0.0.1/' /etc/ssh/sshd_config
$ sudo systemctl restart sshd

SSH 接続ができなくなります。仮想化ソフトのコンソール機能(Hyper-Vの場合は仮想マシン接続)から復旧してください。第5回第27回の知識を使います。

課題2: cron ジョブのスクリプトが動かない

alma-mainで実行:

$ echo '#!/bin/bash' > /tmp/healthcheck.sh
$ echo 'echo "$(date) OK" >> /tmp/health.log' >> /tmp/healthcheck.sh
$ chmod 644 /tmp/healthcheck.sh
$ (crontab -l 2>/dev/null; echo '* * * * * /tmp/healthcheck.sh') | crontab -

1分待っても /tmp/health.log が作成されません。原因を調査し、修復してください。第11回第24回の知識を使います。

課題3: syslog 転送が止まっている

alma-mainで実行:

$ sudo sed -i 's/10.0.1.3/10.0.1.99/' /etc/rsyslog.d/remote.conf
$ sudo systemctl restart rsyslog

alma-sub にログが届かなくなります。原因を調査し、修復してください。第23回の知識を使います。

36回を振り返って

第1回から今日まで、36回にわたって Linux を学んできました。ここで全体を振り返ります。

フェーズ1(第1〜3回): エンジニアの基本動作

まだコマンドを打つ前に、エンジニアとしての「構え」を学びました。報連相の書き方、script による作業記録、セキュリティ意識。技術が変わっても色褪せない基本動作です。今日のシナリオで第一報と完了報告書を書いたとき、第2回の知識がそのまま活きたはずです。

フェーズ2(第4〜15回): サーバーに「触れる」

初めてコマンドを打ち、ファイルを操作し、ユーザーを作り、権限を設定しました。ls, cd, cat, grep, vi, chmod, ps, systemctl。1つ1つ覚えたこれらのコマンドが、今日の障害対応の基本動作になっています。

フェーズ3(第16〜27回): サーバーを「つなげる」

ネットワーク、ファイアウォール、ログ管理、ストレージ、SSH。1台のサーバーを、ネットワーク越しに他のサーバーやサービスと連携させる技術を学びました。シナリオ1でfirewalldを、シナリオ2でSELinuxを、シナリオ3でcronを調べたとき、フェーズ3の知識が土台になっていたはずです。

フェーズ4(第28〜36回): サーバーを「動かし続ける」

SELinux、Webサーバー、データベース、バックアップ、監視、セキュリティ、Git、Ansible。構築だけでなく「運用」するための技術を学びました。そして今日、意図的に壊した環境を自分の手で直す体験をしました。

第1回で掲げたゴール

第1回で、この講座のゴールを以下のように示しました。

  • Linux サーバーの初期構築を手順書なしで実施できる
  • Apache + MariaDB の環境を1人で構築・設定できる
  • ファイアウォール(firewalld)を要件に合わせて設定できる
  • 障害発生時に「CPU → メモリ → ディスク → ネットワーク」の4リソースを確認し、原因を切り分けられる
  • バックアップの設計・取得・リストア(復元)を一通り実行できる
  • Ansible で基本的な構成管理ができる
  • Git で設定ファイルの変更履歴を管理できる

今日のシナリオ1で、Apache の障害対応と firewalld の設定、LVM の拡張を実践しました。シナリオ2で、MariaDB の障害対応と SELinux のポリシー管理を実践しました。シナリオ3で、プロセスの特定と cron の管理を実践しました。すべてのシナリオで、4リソース確認の初動と Git による変更記録を実践しました。

構築・運用・トラブルシューティング。その3つを、今日の演習で実践しました。

ここから先

36回で身につけた基礎の上に、いくつかの方向に進むことができます。

  • 深掘り: 各テーマ(ネットワーク、セキュリティ、データベース等)の専門書やドキュメントで知識を深める
  • 横展開: コンテナ技術(Docker/Kubernetes)、クラウド(AWS/Azure/GCP)、CI/CD など隣接する領域に挑戦する
  • 資格取得: LPIC-1 / LinuC レベル1 は本講座の知識で合格圏内です。学習のペースメーカーとして活用してください

36回お疲れさまでした。

わからないことは今後もたくさん出てきます。でも「何を調べればいいかわからない」と「何を調べればいいかはわかる」の間には大きな差があります。あなたは今、後者の側にいます。man コマンドを引き、ログを読み、公式ドキュメントを探す。その方法を知っている。それが36回で手に入れた一番の財産です。

理解度チェック

以下の記述が正しいか(○)、誤っているか(×)を考えてから、答えを確認してください。

問1: 障害の第一報は原因が完全に判明してから出す。

答え: ×(第一報は速報性が最優先です。原因が不明でも「何が起きているか」「誰が対応しているか」を即座に報告します)

問2: 「サーバーが遅い」という報告があったら、まず CPU だけ確認すればよい。

答え: ×(4リソース(CPU・メモリ・ディスク・ネットワーク)すべてを確認します。「遅い」の原因はCPUとは限りません)

問3: systemctl --failed で何も表示されなければ、サーバーに問題はない。

答え: ×(--failed は systemd 管理下のサービスだけを対象とします。cron ジョブの暴走やユーザープロセスの問題は表示されません。シナリオ3で体験した通りです)

問4: 障害対応中は script コマンドで作業ログを取るべきである。

答え: ○(作業ログは完了報告書の作成、振り返り、再発時の参考資料として役立ちます)

問5: 復旧したら、動作確認の前に完了報告を出してよい。

答え: ×(修復後は必ず動作確認を行います。「修復したつもりが直っていなかった」はよくある失敗です)

問6: firewall-cmd--permanent なしで追加した設定は、firewall-cmd --reload を実行すると消える。

答え: ○(--permanent なしの変更はランタイム設定です。--reload やシステム再起動で永続設定に戻るため消えます)

問7: 障害対応で設定変更をしたら、Git で記録すべきである。

答え: ○(「いつ・何を・なぜ変更したか」を記録することで、次回の障害対応や設定の棚卸しに役立ちます)

問8: 根本原因を特定せず、表面的な症状だけ解消して完了とすべきではない。

答え: ○(「動いた」と「直った」は違います。根本原因が残っていれば再発します)

シリーズ一覧

フェーズ1: エンジニアのいろは

フェーズ2: Linux基礎

フェーズ3: ネットワークとインフラ基盤

フェーズ4: サーバー構築と運用