AI・機械学習

サーバーのログ調査・障害対応にAI(LLM)を使う実践テクニック

サーバーのログ調査・障害対応にAI(LLM)を使う実践テクニック
目次
  1. AI に投げる前に集計する。7 日分 157 件のエラーは、実際に見るべき 9 件まで減った
  2. なぜ生ログをそのまま投げてはいけないのか
  3. ログの大半は同じ 1 行の繰り返し
  4. トークンを無駄に使う
  5. 機密が混ざる
  6. 手順 1:まず件数を数える
  7. 優先度で絞って数える
  8. どのサービスが出しているのか
  9. ディスクの使用量も見ておく
  10. 手順 2:正規化してパターンに畳む
  11. IP・ポート・ユーザー名を伏せてから数える
  12. 実際に出てきた 8 パターン
  13. ノイズの見分け方
  14. 手順 3:残ったものだけを AI に投げる
  15. ノイズを除外して抽出する
  16. 聞き方を具体的にする
  17. それでも自分で確かめる
  18. 機密ログはローカル LLM に投げる
  19. 外に出せないログがある
  20. Ollama をローカルに置く
  21. VPS 上で動かすなら容量に注意
  22. 丸投げしないための鉄則
  23. 件数を先に出す
  24. 正規化してから渡す
  25. AI の答えを別経路で確かめる
  26. よくある質問
  27. Q1. journalctl のエラーは何件くらいが正常ですか?
  28. Q2. kex_exchange_identification のエラーは危険ですか?
  29. Q3. ログを AI に投げるとき何をマスクすべきですか?
  30. Q4. ローカル LLM は VPS 上で動かせますか?
  31. Q5. journal が肥大化したらどうすればいいですか?
  32. まとめ

※本ページには広告(アフィリエイトプログラム等)が含まれます。掲載しているログと件数は 2026年8月16日時点で運用中の VPS(Debian 12・メモリ 958MB)から採取した実測値です。ユーザー名と IP はマスクしています。

AI に投げる前に集計する。7 日分 157 件のエラーは、実際に見るべき 9 件まで減った

サーバーのログを AI に読ませるとき、生ログをそのまま貼るのがいちばん効率が悪いです。

手元の VPS で直近 7 日間のエラーを数えたら 157 件ありました。ところが正規化して集計すると、137 件(87%)は SSH ポートへの総当たりスキャンで、対処のしようがないノイズでした。本当に人間が見るべきだったのは残りの 9 件です。

  • まず `wc -l` で件数を数えてください。規模が分からないと打ち手が決まりません
  • IP・ポート・ユーザー名を正規化してから `uniq -c` にかけると、157 行が 8 パターンに畳まれます
  • ノイズを除いた残りだけ AI に投げれば、トークンも時間も 1 桁減ります
  • ログには IP・ユーザー名・パスが混ざります。外部の AI に投げる前にマスクしてください
  • 「このログを見て」と丸投げすると、ノイズに引きずられた回答が返ってきます

なぜ生ログをそのまま投げてはいけないのか

ログの大半は同じ 1 行の繰り返し

サーバーのエラーログは、種類が多いのではなく同じ行が大量に繰り返されるのが普通です。IP やポート番号だけが違うので、テキストとしては全部別行に見えます。

そのまま貼ると、AI は大量に発生している事象を重要だと解釈します。実際にはただのスキャンなのに、そこに引きずられた回答が返ってきます。

トークンを無駄に使う

157 行を貼るのと、8 パターンに畳んで貼るのとでは、消費するトークンが 1 桁違います。有料 API を使っているなら、そのまま費用差になります。

機密が混ざる

ログには接続元 IP、OS のユーザー名、ホームディレクトリのパスがそのまま出ます。外部のサービスに投げる前に、何が含まれているかを自分で把握しておく必要があります。

手順 1:まず件数を数える

優先度で絞って数える

最初にやるのは読むことではなく数えることです。`journalctl` は優先度で絞れるので、エラー以上だけを対象にします。

$ journalctl --since "-7d" -p err --no-pager | wc -l
157

7 日で 157 件。この数字が出た時点で、全部読むという選択肢が消えます。人力で読む上限はせいぜい数十件です。

どのサービスが出しているのか

次に発生源を数えます。JSON 出力にすると機械的に集計できます。

$ journalctl --since "-7d" -p err --no-pager -o json \
  | python3 -c "
import sys, json, collections
c = collections.Counter()
for line in sys.stdin:
    d = json.loads(line)
    c[d.get('_SYSTEMD_UNIT') or d.get('SYSLOG_IDENTIFIER') or '?'] += 1
for k, v in c.most_common(8):
    print(f'{v:6d}  {k}')
"
   105  ssh.service
    32  sshd
     7  session-631657.scope
     4  session-631659.scope
     2  session-617752.scope

105 + 32 = 137 件が SSH 由来でした。全体 157 件の 87% です。この時点で、SSH のノイズを除いたら何が残るかという問いに変わります。

ディスクの使用量も見ておく

$ journalctl --disk-usage
Archived and active journals take up 503.5M in the file system.

メモリ 958MB・ディスク 99GB の VPS で journal が 503.5MB。上限を設定していないと際限なく増えるので、`SystemMaxUse` を明示しておくと安全です。

手順 2:正規化してパターンに畳む

IP・ポート・ユーザー名を伏せてから数える

ここが一番効きます。変動する部分を置換してから `uniq -c` にかけると、157 行が一気に畳まれます。マスクを兼ねられるので、外部の AI に投げる前処理としても都合がいいです。

$ journalctl --since "-7d" -p err --no-pager -o cat \
  | sed -E "s/[0-9]{1,3}(\.[0-9]{1,3}){3}/<IP>/g;
            s/port [0-9]+/port <N>/g;
            s/user [A-Za-z0-9_.-]+/user <USER>/g" \
  | sort | uniq -c | sort -rn | head -8

実際に出てきた 8 パターン

手元の VPS で実行した結果がこれです。

件数 メッセージ 正体
76 kex_exchange_identification: Connection closed by remote host スキャン
25 kex_exchange_identification: read: Connection reset by peer スキャン
23 banner line contains invalid characters スキャン
7 pam_unix(sudo:auth): conversation failed 要確認
7 pam_unix(sudo:auth): auth could not identify password 要確認
5 client sent invalid protocol identifier “GET / HTTP/1.0” スキャン
4 client sent invalid protocol identifier “\026\003\001\001” スキャン
2 a password is required ; USER=root 要確認

157 行が 8 行になりました。この 8 行なら人間がそのまま読めますし、AI に投げるコストもほぼゼロです。

ノイズの見分け方

上位 3 つの `kex_exchange_identification` は、SSH の鍵交換に入る前に切断された記録です。認証にすら到達していないので、鍵認証にしてある限り実害はありません。

面白いのは下のほうの 2 つです。`”GET / HTTP/1.0″` は SSH ポートに HTTP を投げてきたスキャナ、`”\026\003\001\001″` は TLS のハンドシェイク(0x16 0x03 0x01)を投げてきたスキャナです。ポート番号を変えていても、片っ端から総当たりされていることが分かります。

手順 3:残ったものだけを AI に投げる

ノイズを除外して抽出する

スキャン由来を除くと、残るのは sudo 関連の 9 件でした。ここだけ切り出します。

$ journalctl --since "-7d" -p err --no-pager -o cat \
  | grep -v "kex_exchange_identification" \
  | sed -E "s/\[[A-Za-z0-9_-]+\]/[<USER>]/g; s#/home/[A-Za-z0-9_-]+#/home/<user>#g"

置換をここでも噛ませておくのが要点です。ユーザー名とホームディレクトリのパスがそのまま出るので、外部の AI に渡すなら必須の一手間になります。

聞き方を具体的にする

投げるときは「見て」ではなく、判断してほしいことを明示します。

$ journalctl --since "-7d" -p err --no-pager -o cat \
  | grep -v kex_exchange_identification \
  | claude -p "このログのうち、対処が必要なものと、
無視してよいものに分類してください。
判断の根拠も 1 行ずつ付けてください。"

今回の 9 件は、非対話のシェルから `sudo` を実行してパスワードを求められ、入力できずに失敗した記録でした。攻撃ではなく自分の運用の副作用です。ここまで絞れていれば、AI の回答も検証しやすくなります。

それでも自分で確かめる

AI の分類は出発点であって結論ではありません。無視してよいと言われたものこそ、1 件だけ手で裏を取るくらいでちょうどいいです。

機密ログはローカル LLM に投げる

外に出せないログがある

アクセスログには利用者の IP が入りますし、アプリケーションログにはメールアドレスやトークンが混ざることがあります。置換で消しきれる自信がないものは、そもそも外に出さないのが確実です。

Ollama をローカルに置く

その場合はローカル LLM を使います。手元のマシンで動かして、ログはネットワークの外に出しません。

$ ollama run qwen2.5-coder:7b "次のログで対処が必要なものを挙げて" < errors.txt

VPS 上で動かすなら容量に注意

今回ログを採取した VPS はメモリ 958MB です。7B クラスのモデルは載りません。ローカル LLM を動かすなら、ログを収集するサーバーとは別に、メモリに余裕のある環境を用意してください。

丸投げしないための鉄則

件数を先に出す

読む前に数える。157 件なのか 5 件なのかで、打ち手がまったく変わります。

正規化してから渡す

変動部分を置換して `uniq -c`。マスクと圧縮を同時にやれます。今回は 157 行 → 8 行まで畳めました。

AI の答えを別経路で確かめる

無視してよいという回答をそのまま信じない。1 件でいいので元のログを開いて突き合わせます。ログ調査でいちばん高くつくのは、ノイズを重大事だと誤認することと、その逆です。

よくある質問

Q1. journalctl のエラーは何件くらいが正常ですか?

件数ではなく内訳で判断します。今回の VPS は 7 日で 157 件ありましたが、137 件(87%)は SSH ポートへのスキャンでした。インターネットに露出したサーバーなら、この種のノイズは日常的に出ます。

Q2. kex_exchange_identification のエラーは危険ですか?

鍵認証のみにしてあるなら実害はありません。SSH の鍵交換に入る前に切断された記録で、認証にすら到達していません。ただし件数が急増したら、遮断の設定を見直す合図にはなります。

Q3. ログを AI に投げるとき何をマスクすべきですか?

IP アドレス・OS のユーザー名・ホームディレクトリのパス・トークンの 4 つが最低ラインです。`sed` で置換してから渡せば、マスクとログの圧縮を同時に達成できます。

Q4. ローカル LLM は VPS 上で動かせますか?

メモリ次第です。今回の VPS はメモリ 958MB で、7B クラスのモデルは載りません。ログ収集用のサーバーと、モデルを動かす環境は分けて考えてください。

Q5. journal が肥大化したらどうすればいいですか?

`SystemMaxUse` を明示します。今回の環境では journal が 503.5MB を占めていました。上限を設定しておかないと、ディスクを圧迫してから気づくことになります。

まとめ

AI にサーバーのログを読ませるときは、投げる前に集計するかどうかで結果がまったく変わります。今回の実測では 7 日 157 件から 8 パターンへ、そして要対処 9 件まで絞れました。

まず `journalctl -p err | wc -l` で数えます。次に `sed` で置換してから `uniq -c` で畳みます。マスクも兼ねられます。最後に残りだけを、判断してほしいことを明示して投げます。

数値は 2026年8月16日時点で運用中の VPS から採取したものです。環境が違えば内訳も変わるので、まずは自分のサーバーで同じコマンドを 1 回叩いてみてください。サーバーの初期構築から見直すならさくらの VPS の初期セットアップ、常駐プロセスの管理はsystemd のユニットファイル、遮断の設定はufw の設定にまとめています。