🎯 最終演習

Linuxコマンドでログを解析し、障害の原因を突き止めよう(総合演習)

ここまでの Linux レッスンで覚えたコマンドをひとつの調査に総動員します

想定はこうです。「昼ごろサイトが重かったらしい。ログを見て原因を調べておいて」——現場でいちばんよく振られる仕事のひとつです。

やることはログを見つける → 規模をつかむ → エラーだけ抜き出す → 原因ごとに整理する → 犯人を特定する。手順そのものは、扱うログが何であっても変わりません。

ページの一番下に本物の疑似ターミナルがあります。状態はコマンドをまたいで続くので、上から順に打てばそのまま完走できます。

完成イメージ

最後まで進むと、こう表示されるところまで作ります。下の実行結果は、このページを作るときに実際にコードを走らせて得たものです。

$ grep timeout app.log
10:02:17,ERROR,database connection timeout
10:02:25,ERROR,database connection timeout
15:58:02,ERROR,database connection timeout
$ grep 500 access.log
10:02:17,500,/api/orders
12:44:52,500,/api/payment
15:58:02,500,/api/orders

STEP 1ログの置き場所を見つける

🎯 このステップのゴール: ls と cd でログのあるディレクトリまで辿り着く

調査は「どこにログがあるか」を探すところから始まります。lsで今いる場所の中身を見て、logsというディレクトリを見つけてcdで入ります。

lsの表示で末尾に/が付いているものがディレクトリです。ファイルとディレクトリを見分ける手がかりになります。

移動したらpwdで今いる場所を確かめる癖をつけてください。ディレクトリを間違えたまま作業して、見当違いのファイルを調べていた——というのは実際によくあります。

ls -lにするとサイズや権限まで見えます。ログ調査ではファイルサイズが手がかりになることがあり、異常に大きいログは何かが大量に出力されている印です。

本番のサーバーでは、ログはたいてい/var/log/の下にあります。cd /var/logから始めるのが定石です。

打つコマンド
ls
cd logs
pwd
ls -l
実行結果
$ ls
data.csv  fruits.txt  logs/  notes.txt  project/  sorted-fruits.txt
$ cd logs
$ pwd
/home/user/logs
$ ls -l
-rwxr-xr-x  1 user  staff    141  access.log
-rwxr-xr-x  1 user  staff    360  app.log

STEP 2まず全体の規模をつかむ

🎯 このステップのゴール: wc で行数を数え、head と tail で前後を覗く

いきなりcatで全部表示したくなりますが、本番のログは数万行あります。画面が流れるだけで何も分かりません。

まずwc app.logどのくらいの量なのかを確かめます。左から行数・単語数・バイト数です。10行ならそのまま読めますが、10万行なら読み方を変える必要がある——その判断のための一手です。

次にheadtail前後だけを覗きます-n 3で3行だけです。

ログ調査ではtailのほうを先に見ます。ログは下に行くほど新しいので、「今起きている問題」は末尾にあるからです。実務ではtail -fで流れ続けるログを眺めながら操作を再現する、という使い方をよくします。

今回のログは「時刻,レベル,メッセージ」のカンマ区切りだと分かりました。形式が分かれば、あとは機械的に絞り込めます

打つコマンド
wc app.log
head -n 3 app.log
tail -n 3 app.log
実行結果
$ wc app.log
10 28 360 app.log
$ head -n 3 app.log
09:12:03,INFO,application started
09:15:41,INFO,user login id=204
10:02:17,ERROR,database connection timeout
$ tail -n 3 app.log
13:05:10,WARN,slow query 2.4s
14:20:33,INFO,backup finished
15:58:02,ERROR,database connection timeout

STEP 3エラー行だけを抜き出す

🎯 このステップのゴール: grep で ERROR を含む行だけに絞る

ここからが本番です。grep ERROR app.logERRORを含む行だけが残ります。

grepはログ調査で最もよく使うコマンドです。何万行あっても、必要な行だけが一瞬で出てきます。「ログを読む」というのは、実際にはほとんどgrepで絞る」作業です。

結果は4行。10行中4行がエラーという、かなり良くない状態です。

ここで大文字小文字が区別されることに注意してください。grep error app.logでは1行も出ません。実務ではgrep -iで区別せずに探すことが多く、ログの書式が揃っていないときに効きます。

数を数えたいときは本来grep ERROR app.log | wc -lとパイプでつなぎます。この疑似ターミナルはパイプに対応していないので、ここでは出てきた行を目で数えてください。本物のサーバーではこの書き方が基本になります。

WARNも見ておくと、エラーの前後で何が起きていたかが見えてきます。

打つコマンド
grep ERROR app.log
grep WARN app.log
実行結果
$ grep ERROR app.log
10:02:17,ERROR,database connection timeout
10:02:25,ERROR,database connection timeout
12:44:52,ERROR,payment api returned 500
15:58:02,ERROR,database connection timeout
$ grep WARN app.log
10:02:19,WARN,retrying connection
13:05:10,WARN,slow query 2.4s

STEP 4原因ごとに整理する

🎯 このステップのゴール: cut でメッセージ列だけを取り出し、sort で同じものを隣に並べる

エラーが4件あることは分かりました。次に知りたいのは「何が原因なのか」「同じ原因が繰り返されているのか」です。

cut -d , -f 3 app.log3列目(メッセージ)だけを取り出します。-d区切り文字-f何列目かです。時刻やレベルが消えて、メッセージだけが並びます。

次にsortを通すと同じ文字列が隣り合って並びます。するとdatabase connection timeout3回並んでいるのが目で見て分かります。

これが「集計」の第一歩です。本来はsort | uniq -cとつないで件数を出しますが、この疑似ターミナルはパイプとuniq -cの件数表示に対応していないため、ここでは並べるところまでにしています。本物のサーバーではcut -d , -f 3 app.log | sort | uniq -c | sort -rnが定番の一行です。

この演習ではcut -d , -f 3と空白を空けて書いてください。cut -d, -f3と詰めて書くと、この疑似エンジンではエラーを出さずに1列目を返してしまいます(本物のLinuxでは詰めて書いても正しく動きます)。

打つコマンド
cut -d , -f 3 app.log
sort app.log
実行結果
$ cut -d , -f 3 app.log
application started
user login id=204
database connection timeout
retrying connection
database connection timeout
user login id=311
payment api returned 500
slow query 2.4s
backup finished
database connection timeout
$ sort app.log
09:12:03,INFO,application started
09:15:41,INFO,user login id=204
10:02:17,ERROR,database connection timeout
10:02:19,WARN,retrying connection
10:02:25,ERROR,database connection timeout
11:30:08,INFO,user login id=311
12:44:52,ERROR,payment api returned 500
13:05:10,WARN,slow query 2.4s
14:20:33,INFO,backup finished
15:58:02,ERROR,database connection timeout

STEP 5犯人を絞り込む

🎯 このステップのゴール: キーワードで直接引いて、件数と時刻を確かめる

怪しいのはdatabase connection timeoutです。これだけを狙って引きます

grep timeout app.log——3件出ました。時刻を見ると10:02:17、10:02:25、15:58:02。10時台に2件が8秒差で連続し、午後にもう1件です。

時刻の固まりは大きな手がかりです。8秒差で2回というのは、1回失敗して再試行し、それも失敗したという形です。実際、WARNにretrying connectionが出ていたのと符合します。

もうひとつのログも見てみましょう。grep 500 access.logサーバーエラーを返したアクセスが引けます。時刻が10:02:1712:44:5215:58:02——app.logのERRORと時刻がぴったり一致します

2つのログを時刻で突き合わせるのは、障害調査の基本です。「アプリ側のエラー」と「利用者から見たエラー」が同じ時刻で繋がると、原因と影響が一本の線になります

打つコマンド
grep timeout app.log
grep 500 access.log
実行結果
$ grep timeout app.log
10:02:17,ERROR,database connection timeout
10:02:25,ERROR,database connection timeout
15:58:02,ERROR,database connection timeout
$ grep 500 access.log
10:02:17,500,/api/orders
12:44:52,500,/api/payment
15:58:02,500,/api/orders

STEP 6分かったことをまとめる

🎯 このステップのゴール: 調査結果を報告できる形に言葉でまとめる

コマンドはここまでです。最後は分かったことを人に伝えられる形にします。調べただけで終わっては仕事になりません。

今回のログから言えるのは、次の3点です。

1. エラーは10行中4件。うち3件が同じ原因(database connection timeout)で、残り1件が決済APIの500エラー。

2. 発生時刻は10:02台に2件(8秒差)と15:58に1件。8秒差の連続は、再試行して再び失敗した形。WARNのretrying connectionと符合する。

3. 利用者にも影響が出ている。access.logの500エラーが同じ時刻に記録されており、/api/orders——注文の処理——が失敗している。

ここまで書ければ、「データベースへの接続がときどきタイムアウトしていて、注文が通らなくなっている」という報告になります。あとは接続数の上限や、ネットワークの状態を疑う番です。

ログ調査のコツは、いきなり原因を探さないこと。「量をつかむ → 絞る → 並べる → 突き合わせる」の順に手を動かせば、たいていの障害は形が見えてきます。

下の疑似ターミナルで、STEP1から自分の手で通してみてください。

打つコマンド
grep ERROR app.log
wc access.log
実行結果
$ grep ERROR app.log
10:02:17,ERROR,database connection timeout
10:02:25,ERROR,database connection timeout
12:44:52,ERROR,payment api returned 500
15:58:02,ERROR,database connection timeout
$ wc access.log
6 6 141 access.log

仕上げ自分で最初から打ってみよう

🎯 このステップのゴール: ここまでの流れを、自分の手で最後まで通す

下は本物の疑似ターミナルです。まっさらな状態から始まるので、STEP1のコマンドから順に打って、マージまで辿り着いてください。読んで分かった気になるのと、自分で打てるのとは別物です。

詰まったら上のステップに戻って構いません。resetと打てば最初からやり直せます。

$

よくある質問

パイプ(|)が使えないのはなぜですか?

このサイトの疑似ターミナルが対応していないためです。本物のLinuxではgrep ERROR app.log | wc -lのようにコマンドをつなげられ、ログ調査ではこのつなぎ方こそが中心になります。

この演習ではコマンドを1つずつ実行する形にしていますが、考え方はまったく同じです。「絞る」「数える」「並べる」を順に当てているだけで、本物ではそれを1行で書ける、という違いです。

本物のサーバーではログはどこにありますか?

多くは/var/log/の下です。/var/log/nginx/access.logのようにサービスごとに分かれています。

読むには管理者権限が要ることが多いので、sudoを付けるか、ログを読める権限を持つユーザーで入ります。また本番のログは日ごとに分割・圧縮されていることが多く、app.log.1.gzのようなファイルはzgrepで直接検索できます。

cut の書き方に空白が要るのはなぜですか?

この疑似エンジンの制限です。本物のLinuxではcut -d, -f3と詰めて書けますし、そちらのほうが一般的です。

ただしこの疑似ターミナルでは詰めて書くとエラーを出さずに1列目を返してしまうので、この演習ではcut -d , -f 3と空けて書いてください。実機で使うときは、どちらでも構いません。

🚩 次はこのカテゴリへ

ログから「接続がタイムアウトしている」ところまで辿り着いたら、次に疑うのはネットワークそのものです。どこで詰まっているのか、経路は正しいのか——ネットワークカテゴリでは、その調べ方を疑似ターミナルで練習できます。

ネットワークのレッスンへ進む
広告スペース(バナー)
広告スペース(記事内)