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 + ping | NICの状態と疎通。IPが付いているか、外部と通信できるか |
深堀りコマンド(リソース別)
初動5コマンドで異常が見つかったら、該当するリソースを深堀りします。
| リソース | 深堀りコマンド | 用途 |
|---|---|---|
| CPU | ps aux --sort=-%cpu | head | CPU消費の多いプロセスを特定 |
| CPU | top -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つのシナリオすべて、以下の流れで進めます。これは実際の障害対応と同じサイクルです。
- script 開始: 作業ログの記録を開始する(第2回)
- 第一報: 状況を報告する(事実と推測を分ける)
- 初動確認: 4リソース + サービス状態を確認する
- 切り分け・原因特定: 異常箇所を深堀りし、根本原因を突き止める
- 修復: 原因に対処する
- 動作確認: 修復が正しく行われたことを確認する
- 完了報告書: 原因・対応内容・再発防止策を記録する
- Git 記録: 設定変更があればコミットする
- 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基礎
- 第4回 Linuxとは何か+環境確認
- 第5回 SSH接続とターミナル操作
- 第6回 ファイルシステムとディレクトリ構造
- 第7回 基本コマンド(ファイル操作)
- 第8回 基本コマンド(テキスト処理・パイプとリダイレクト)
- 第9回 viエディタ
- 第10回 ユーザーとグループ管理
- 第11回 パーミッションと所有権
- 第12回 プロセス管理
- 第13回 systemd
- 第14回 シェルスクリプト入門
- 第15回 フェーズ2まとめ演習
フェーズ3: ネットワークとインフラ基盤
- 第16回 ネットワーク基礎
- 第17回 ネットワーク設定と疎通確認
- 第18回 企業ネットワークの仕組み
- 第19回 パッケージ管理
- 第20回 ファイアウォール(firewalld)
- 第21回 ボンディング/チーミング
- 第22回 VLAN
- 第23回 ログ管理
- 第24回 cron / systemd timer
- 第25回 ストレージ管理(LVM)
- 第26回 シェルスクリプト実践
- 第27回 SSH応用
フェーズ4: サーバー構築と運用
- 第28回 SELinux
- 第29回 Webサーバー構築(Apache/Nginx)
- 第30回 データベース基礎(MariaDB)
- 第31回 バックアップと復旧
- 第32回 監視入門
- 第33回 セキュリティ実践
- 第34回 Git基本操作
- 第35回 自動化と構成管理(Ansible)
- 第36回 トラブルシューティング(総合演習・最終回)
