【無料ツール】画像をPDFに変換するPhotoPDF Appを公開しました!

Linuxエンジニアの生成AI活用 第7回:AIを監視オペレーターにする!Cron×LLMの「自動レポートボット」

こんにちは!「LINUX工房」メインライターの「リナックス先生」よ。

前回の第6回では、社内マニュアルをAIに読み込ませて、自社専用の最強コンサルタント(簡易RAG)を作る方法を学んだわね。これであなたが「質問」した時の回答精度は完璧になったわ。でも、インフラエンジニアたるもの、ただ待っているだけではダメよ。今回は、あなたが寝ている間もサーバーの健康状態を見守り、毎朝「今日のサーバーの調子と懸念点」を自動で報告してくれる「AI監視オペレーター」を構築するわよ!

コウ君

先生!毎朝出社して一番最初にやるのが、数台のサーバーのCPU使用率やエラーログを順番に見て回ることなんです。何も起きていなければ「異常なし」ってチャットに投げるだけなんですけど、毎日こればかりやっていると自分がロボットになった気分で……。これを全部AIにやってもらうことなんてできるんですか?

リナックス先生

その「自分がロボットになった気分」という感覚、インフラエンジニアとして大正解よ!決まった時間に決まったコマンドを打って、結果をコピペするだけの作業を「トイル(無価値な労働)」と呼ぶの。今日はLinuxの時計仕掛けである『Cron』と、第5回で構築した『ローカルLLM』を結合して、あなたの代わりに働いてくれる部下をサーバー内に作り上げるわよ!

Linuxエンジニアのための生成AIフル活用カリキュラム(全8回)

  1. 第1回:ブラウザを捨てよ!「黒い画面」からAIを呼び出すAPIとcurlの基礎
  2. 第2回:コマンド忘れはもう怖くない!ターミナル専属AIアシスタントの構築
  3. 第3回:難解なエラーログを一瞬で解読!パイプで繋ぐトラブルシューティング
  4. 第4回:手作業をゼロへ!AIに「インフラ自動化スクリプト」を書かせる極意
  5. 第5回:機密データを守れ!「Ollama」で作る完全ローカルなLLM環境構築
  6. 第6回:膨大なマニュアルを瞬時に検索!Linuxサーバー内「簡易RAG」の構築
  7. 【今回】第7回:AIを監視オペレーターにする!Cron×LLMの「自動レポートボット」
  8. 第8回:AI時代のエンジニアサバイバル!セキュリティの壁とこれからのインフラ運用

1. 運用監視の苦痛と「AIオペレーター」という解決策

① 概念と背景(Why)

システム運用の現場において、最も地味でありながら最も重要な業務が「朝のヘルスチェック(稼働確認)」です。前夜から今朝にかけて、CPUのスパイク(急激な上昇)はなかったか、メモリの空き容量(OOMの兆候)は十分か、ディスクの枯渇は進んでいないか、そして深夜のバッチ処理で致命的なエラーログが吐き出されていないか。これらを人間の目で確認し、チームに報告する作業は、インフラエンジニアの貴重な午前中のリソースを容赦なく奪い去ります。

近年、ZabbixやDatadog、Prometheusといった素晴らしい監視ツールが普及し、グラフ化や異常時のアラート通知は自動化されました。しかし、それらのツールが教えてくれるのは「CPUが80%を超えました」「エラーキーワードを検知しました」という「点」の事象に過ぎません。そのアラートを受けて「なぜ上がったのか」「このエラーは過去の事象と関連しているか」「今すぐ緊急対応が必要か、それとも様子見でよいか」という「線」の判断、つまり「文脈の解釈と要約」は、結局のところ人間のエンジニアの脳に依存しているのが現状です。

ここで、生成AI(LLM)の力が爆発的に活きます。AIは単なる数値の羅列やエラーの文字列を読み込むだけでなく、その「意味」を解釈することができます。私たちが構築する「AI監視オペレーター」は、システムの生データ(メトリクスとログ)を一手に引き受け、LLMの推論能力を用いて「昨晩の2時にバックアップ処理の影響で一時的にCPUが上昇しましたが、現在は正常値に落ち着いています。ただし、Webサーバーで権限エラーが3件発生しており、早急な確認を推奨します」といった、人間が書いたような「知的なサマリーレポート」を生成します。これをLinuxの定期実行デーモンである `Cron` と組み合わせることで、あなたは毎朝コーヒーを飲みながら、Slackに届いたAIからの完璧な報告書を読むだけで済むようになるのです。これは単なる自動化ではなく、運用の「自律化」への第一歩なのです。

② 実践手順と完全なコード(How)

AIにレポートを書かせる前に、まずは「AIに判断材料として渡すための生のシステムデータ」を抽出するコマンド群を理解する必要があります。ここでは、Linuxサーバーの「過去の健康状態」を精密に振り返るための定番コマンドの挙動を確認します。

# 1. sysstatパッケージをインストールし、過去のシステム統計情報を取得できるようにする
sudo dnf install sysstat -y
sudo systemctl enable --now sysstat

# 2. sarコマンドを用いて、昨日のCPU使用率の推移(サマリー)を表示する
sar -u -1

# 3. sarコマンドを用いて、今日のメモリ使用率の状況を表示する
sar -r

# 4. dfコマンドでディスクの空き容量を取得し、可読性の高い形式にする
df -h /

③ プロによるコードの「1行・1オプション」徹底解説

  • sudo dnf install sysstat -y:`sysstat` は、Linuxの健康状態を10分おきに記録し続けるインフラエンジニアの「三種の神器」の一つです。インストールして起動(`enable –now`)しておかないと、過去に遡って負荷を調べることができません。
  • sar -u -1:`sar`(System Activity Reporter)のCPU(`-u`)レポートを表示します。`-1` というオプションは「1日前(昨日)」のデータを指します。AIに「昨晩の負荷」を評価させるために必須のオプションです。
  • sar -r:メモリ(RAM)の使用率推移を表示します。ここで出力される `%memused` や `%commit` の数値をAIに見せることで、「メモリリークの兆候」を事前に察知させることができます。
  • df -h /:ファイルシステムのディスク使用量をヒューマンリーダブル(`-h`)で出力します。ディスク枯渇はシステムダウンに直結するため、毎朝のチェック項目から外すことはできません。

④ 現場のリアル(失敗談とノウハウ)

`sar` コマンドは非常に強力ですが、デフォルトでは「画面表示用」にフォーマットされているため、AIにそのまま投げると「カラムがずれている」「午前と午後の表記(AM/PM)が環境によって違う」といった理由で、AIが数値を読み間違える(幻覚を起こす)という罠があります。現場のプロは、AIに確実な数値を渡すために、`sar` の出力を人間向けではなく機械向けに整形するか、あるいは `free` や `uptime` のような単純明快なコマンドの出力を組み合わせて渡すという「AIへの忖度」を行います。AIが賢いからといって、生データを適当に投げつければいいというわけではないのよ!


2. 監視データの収集:sarとjournalctlを用いたシェルスクリプト

① 概念と背景(Why)

AIにシステム状態を正しく評価させるためには、前提となる「入力データ」の質がすべてを決定します。先ほど説明した通り、ただコマンドを乱れ打ちして生ログを結合しただけの数万行のテキストをAIに渡すと、コンテキストウィンドウの限界(トークン超過)に引っかかるだけでなく、重要なエラー情報がノイズに埋もれてしまう「Lost in the middle現象」を引き起こします。

したがって、AIオペレーターの「目」となるシェルスクリプトは、システムから情報を抽出する段階で、徹底的な「要約と選別」を行う必要があります。CPUやメモリの情報は、長々とした時系列データではなく、「1日の平均値」や「ピーク時の最大値」といったサマリーに絞り込みます。また、ログファイル(journalctl)については、正常なアクセスログ(200 OK)はすべて破棄し、「warning」以上の警告ログや「error」のみを抽出し、さらに直近24時間のものだけに限定します。

このように、「AIが読むべき情報だけを綺麗にパッケージングする前処理スクリプト」を書くことこそが、この自動化の最も重要な部分です。情報を削ぎ落とし、純度を高める。Linuxのパイプとテキスト処理コマンド群(`awk`, `grep`, `tail`)の真の力が、AIの頭脳をサポートするためのデータエンジニアリングとして輝き始めます。

② 実践手順と完全なコード(How)

サーバーの健康状態(CPU、メモリ、ディスク、エラーログ)を収集し、AIに渡すための一つのテキストデータ(コンテキスト)として組み立てるシェルスクリプトのコア部分を作成します。

#!/bin/bash
# ファイル名: collect_metrics.sh
# 実行権限: chmod u+x collect_metrics.sh

set -euo pipefail

# 一時ファイルの定義
REPORT_DATA="/tmp/server_report_data.txt"
> "${REPORT_DATA}" # ファイルを空にして初期化

echo "サーバーヘルスチェックデータの収集を開始します..."

# --- 1. 基本システム情報の取得 ---
echo "【システム基本情報】" >> "${REPORT_DATA}"
echo "Hostname: $(hostname)" >> "${REPORT_DATA}"
echo "Date: $(date +'%Y-%m-%d %H:%M:%S')" >> "${REPORT_DATA}"
echo "Uptime: $(uptime -p)" >> "${REPORT_DATA}"
echo "" >> "${REPORT_DATA}"

# --- 2. リソース使用状況のサマリー取得 ---
echo "【リソース使用状況 (現在値)】" >> "${REPORT_DATA}"
# メモリ使用量(Mバイト単位)
free -m | awk 'NR==2{printf "Memory Usage: %sMB / %sMB (%.2f%%)\n", $3, $2, $3*100/$2 }' >> "${REPORT_DATA}"
# ディスク使用量(ルートパーティション)
df -h / | awk '$NF=="/"{printf "Disk Usage (/): %d/%dGB (%s)\n", $3,$2,$5}' >> "${REPORT_DATA}"
# CPU負荷(ロードアベレージ)
cat /proc/loadavg | awk '{print "Load Average (1m, 5m, 15m): " $1 ", " $2 ", " $3}' >> "${REPORT_DATA}"
echo "" >> "${REPORT_DATA}"

# --- 3. 過去24時間の深刻なエラーログ抽出 ---
echo "【過去24時間の深刻なエラーログ (直近20件)】" >> "${REPORT_DATA}"
# systemdのジャーナルから、エラーレベル(err)以上のログを過去24時間分抽出し、最新20行を取得
journalctl -p err --since "24 hours ago" --no-pager | tail -n 20 >> "${REPORT_DATA}"

echo "データの収集が完了しました。出力ファイル: ${REPORT_DATA}"
cat "${REPORT_DATA}"

③ プロによるコードの「1行・1オプション」徹底解説

  • > “${REPORT_DATA}”:リダイレクトの左側を空にすることで、指定したファイルの中身を瞬時に空っぽ(初期化)にするLinuxのイディオム(慣用句)です。前日のデータが混ざらないようにするための必須処理です。
  • uptime -p:システムが起動してから現在までどれくらい稼働し続けているか(連続稼働時間)を人間が読みやすい形式(pretty format)で出力します。意図せぬ再起動が発生していないかを確認するための指標です。
  • awk ‘NR==2{printf …}’:`awk` コマンドの真骨頂です。`free -m` の出力結果から2行目(NR==2:物理メモリの行)を抽出し、使用量($3)と全体量($2)を取り出して、即座にパーセンテージを計算($3*100/$2)して整形出力しています。AIに計算させるのではなく、シェル側で計算を済ませておくのが確実な設計です。
  • journalctl -p err –since “24 hours ago” –no-pager:昨日の朝から今朝までの間に起きた「エラー(err)以上」のログだけを抜き出します。`–no-pager` を付けないと `less` コマンドのような対話モードになりスクリプトが停止してしまうため、自動化においては絶対につけるべきオプションです。
  • tail -n 20:万が一エラーが1万行出ていた場合でも、AIのトークンを使い潰さないように最新の20行(エラーの結末)だけに情報を絞り込む安全装置です。

④ 現場のリアル(失敗談とノウハウ)

`journalctl` でエラーログを抽出する際、システムによってはSSHのブルートフォース攻撃(パスワード総当り)による認証エラーが数万行も記録されており、本当に重要なアプリケーションのエラーが `tail -n 20` の中に全く入らない、という「ログの押し出し事故」が現場でよく発生します。プロはこれを防ぐため、`journalctl -p err | grep -v “sshd”` のように、日常茶飯事であるノイズログを `grep -v`(除外)で弾き飛ばしてから `tail` に渡すという、もう一段階深いフィルタリングを施します。AIに渡すデータの「品質管理」、これこそがオペレーターの腕の見せ所よ!


3. AIによるデータ解析とレポート生成:aichatのバッチ処理化

① 概念と背景(Why)

綺麗にパッケージングされたシステムデータ(コンテキスト)が完成しました。次に行うのは、このデータをローカルLLMに渡し、人間が読みやすい「日報(サマリーレポート)」の形に書き直させる作業です。第5回で導入したOllamaとaichatがここで再び活躍しますが、今回は人間がターミナルで対話するわけではありません。シェルスクリプトの中から、完全に裏方(バッチ処理)としてAIを呼び出します。

ここで極めて重要になるのが、AIへの「システムプロンプト(指示書)の品質」です。AIにただ「このデータを要約して」と投げると、「システムは正常です。メモリは〇〇MB使っています。エラーが数件あります」という、小学生の作文のような無味乾燥な文章が返ってきます。これでは、経営層や他部門のマネージャーに共有できるレベルのレポートとは言えません。

インフラの報告書にはフォーマット(型)があります。まず【総評】でシステム全体の健全性を一言で述べ、次に【リソース状況】で特筆すべき負荷の有無を指摘し、最後に【懸念点・アラート】でエラーの内容と「今すぐ対応が必要か否か」の考察を加える。この厳格な型をAIに守らせ、あたかも「10年戦士のシニアSRE(サイト信頼性エンジニア)」が書いたかのような、知的で簡潔、かつ具体的なアクションを促すMarkdown形式のレポートを生成させることが、このフェーズの最大の目標です。

② 実践手順と完全なコード(How)

先ほど作成したデータファイル(/tmp/server_report_data.txt)を読み込み、厳密に設計されたプロンプトと結合して `aichat` に流し込み、最終的なレポートファイルを生成するスクリプトを追記します。

# 前項のスクリプト (collect_metrics.sh) の続きに以下を追記します

FINAL_REPORT="/tmp/daily_ai_report.md"
> "${FINAL_REPORT}"

echo "AIによるデータ解析とレポート生成を開始します..."

# 厳格な指示を記述したプロンプトを構築
AI_PROMPT="あなたは優秀なシニアSRE(サイト信頼性エンジニア)です。
以下の【システム生データ】を解析し、IT部門のマネージャー向けに毎朝の『サーバー稼働状況レポート』を作成してください。

【絶対遵守ルール】
1. レポートはMarkdown形式で出力し、以下の3つの見出しを必ず含めること。
   - ## 1. 総合ステータス(正常/警告/異常 の一言判定と、その理由の簡潔な要約)
   - ## 2. リソース分析(CPU/メモリ/ディスクの状況から読み取れる傾向と余裕度)
   - ## 3. セキュリティ&エラー考察(ログに記載されたエラーの深刻度と、推奨されるアクション)
2. 挨拶や「レポートを作成しました」などの前置き、後書きは一切不要。
3. 単なる数値の羅列ではなく、プロの視点からの「解釈(このままでよいか、対処が必要か)」を記述すること。

【システム生データ】
$(cat ${REPORT_DATA})"

# aichatをバッチモード(標準入力からプロンプトを読み込む)で実行し、結果をファイルに出力
echo "${AI_PROMPT}" | aichat --role "system" "指示を厳守し、Markdownのみを出力せよ。" > "${FINAL_REPORT}"

echo "AIレポートの生成が完了しました。"
cat "${FINAL_REPORT}"

③ プロによるコードの「1行・1オプション」徹底解説

  • $(cat ${REPORT_DATA}):コマンド置換を使って、先ほど一生懸命整形した生データファイルの中身を、プロンプトの文字列の中にそのまま展開(注入)しています。これにより、指示とデータが一体化した巨大なテキスト塊が完成します。
  • 【絶対遵守ルール】:箇条書きと見出しの構造を明示的に指定することで、LLM特有の「出力フォーマットのブレ」を抑え込みます。特に「挨拶の禁止」は、後でSlack等に通知する際に画面が不要な文字で埋め尽くされるのを防ぐための必須テクニックです。
  • echo “${AI_PROMPT}” | aichat … > “${FINAL_REPORT}”:完成したプロンプトをパイプで `aichat` に渡し、その標準出力(AIが考えた回答)をリダイレクト `>` によって最終的なMarkdownファイルに上書き保存します。ここでコマンドが完全に裏方として機能しています。

④ 現場のリアル(失敗談とノウハウ)

ローカルの軽量モデル(Llama 3 8Bなど)に日本語で複雑な指示を出すと、時折「AIが勝手に英語で回答してくる」という言語のスイッチング現象(Language drifting)が発生することがあります。これを防ぐため、現場ではプロンプトの末尾に「必ず日本語で出力してください(MUST reply in Japanese.)」と念押しの指示を追加するのがコツです。また、AIの生成処理には数十秒から数分の時間がかかるため、スクリプトを実行して画面が固まったように見えても焦って `Ctrl+C` で強制終了しないこと。バックグラウンドでAIが一生懸命考えているのだから、プロならじっと待つ余裕を持つのよ!


4. Cronへの登録とSlack通知:完全自動化の完成と運用ノウハウ

① 概念と背景(Why)

AIが書いた素晴らしいレポートファイルがサーバー内に生成されました。しかし、これを人間が毎日サーバーにログインして `cat` で読みに来るのでは、自動化とは呼べません。本当に「AIがオペレーターとして働いている」状態にするには、完成したレポートを私たちが普段仕事をしている場所(SlackやMicrosoft Teams、あるいはメール)へ自動的に送り届ける仕組み(プッシュ通知)が必要です。

ここで利用するのが、第1回で学んだ `curl` コマンドによるAPI通信です。Slackの「Incoming Webhook」という機能を使えば、指定したURLに向けて `curl` でテキストを投げるだけで、特定のチャンネルにメッセージを投稿させることができます。システムから人間へ直接アプローチする経路を作るわけです。

そして、この一連のスクリプト(データ収集 → AI解析 → Slack通知)を、「毎朝8時0分に自動で実行する」ようにスケジュール登録します。ここで登場するのが、Linuxの歴史と共に歩んできた伝統のジョブスケジューラー「Cron(クロン)」です。Cronに登録されたスクリプトは、あなたが寝ていようが休んでいようが、OSが起動している限り指定された時刻に狂いなく実行されます。これによって初めて、人間を介在しない「完全なる自律型監視システム」が完成するのです。

② 実践手順と完全なコード(How)

生成されたレポートをSlackへ通知する処理をスクリプトの最後に追加し、それをCronに登録して毎朝の定時実行を仕掛けます。(※SlackのWebhook URLは事前に取得している前提です)

# --- 1. スクリプト(collect_metrics.sh)の最後にSlack通知処理を追記 ---

SLACK_WEBHOOK_URL="https://hooks.slack.com/services/XXXXX/YYYYY/ZZZZZ"
# jqコマンドを使って、改行を含むMarkdownテキストをJSONの文字列として安全にエスケープする
ESCAPED_PAYLOAD=$(jq -n --arg text "$(cat ${FINAL_REPORT})" '{text: $text}')

echo "Slackへレポートを送信しています..."
curl -s -X POST -H "Content-Type: application/json" -d "${ESCAPED_PAYLOAD}" "${SLACK_WEBHOOK_URL}"
echo "すべての処理が完了しました。"
exit 0

# --- 2. 完成したスクリプトをCronに登録する ---
# 現在のユーザーのCron設定を開く
crontab -e

# Vimが開くので、以下の1行を記述して保存(:wq)する
# 毎日午前8時00分にスクリプトを実行し、標準出力とエラー出力をログファイルに保存する設定
00 08 * * * /bin/bash /home/kou/collect_metrics.sh >> /var/log/ai_monitor.log 2>&1

③ プロによるコードの「1行・1オプション」徹底解説

  • jq -n –arg text “$(cat ${FINAL_REPORT})” ‘{text: $text}’:Slackに送るJSONデータを作る際、AIが書いたMarkdownの中には改行(\n)やダブルクォーテーション(”)が大量に含まれています。これをそのまま `curl -d ‘{“text”: “…”}’` と力技で書くと、JSONの文法が壊れて送信エラーになります。`jq` の `–arg` 機能を使うことで、どんな複雑なテキストでも「安全なJSON文字列」に自動で変換(エスケープ)してくれる、プロ必携のテクニックです。
  • crontab -e:Cronのスケジュール設定ファイル(crontab)を編集するための専用コマンドです。
  • 00 08 * * *:Cronの時間指定フォーマットです。左から「分(0)」「時(8)」「日(毎日)」「月(毎月)」「曜日(毎日)」を表します。これで「毎朝8時ジャスト」の指定になります。
  • /bin/bash /home/kou/collect_metrics.sh:Cronで実行するコマンドは、必ず「フルパス」で書くのが絶対的なルールです。スクリプトの中で `aichat` や `jq` を呼んでいる場合も、スクリプト内でパスを通すか、フルパスで書く必要があります。
  • >> /var/log/ai_monitor.log 2>&1:Cronの実行結果(エラーも含めて)をログファイルに追記します。Cronは画面がないため、これをしておかないと「なぜ動かなかったのか」が永遠に謎に包まれてしまいます。

④ 現場のリアル(失敗談とノウハウ)

⚠️ トラブルシューティング / 注意点:Cron最大の罠「環境変数 PATH の消失」
ターミナルから ./collect_metrics.sh と手で実行した時は完璧にSlackに通知が来るのに、翌朝Cronで動かすと何も通知されない。ログを見ると aichat: command not found というエラーが出ている……。これは、初心者が100%踏み抜く「Cronの罠」です。Cronがスクリプトを実行する時、あなたが普段ターミナルで使っている便利な環境変数(PATH など)は一切読み込まれません。真っ新な状態で実行されるのです。これを防ぐため、プロはスクリプトの先頭(シバンの直後)に export PATH=$PATH:/usr/local/bin:/usr/bin のように、必要なコマンド群のPATHを明示的に再定義するか、/usr/local/bin/aichat のように全てのコマンドをフルパスで記述するという泥臭い防衛策をとります。Cronを制する者はインフラ自動化を制すのよ!

コウ君

先生、すごいです!! 翌朝スマホのSlackを見たら、AIから「総合ステータス:正常。ただしメモリ使用率が上昇傾向にあります」っていう、まるで先輩エンジニアが書いたような見事なレポートが届いていました。CronのPATH問題には見事に引っかかりましたけど、ログを見て直せました。これで毎朝の点検作業が完全にゼロになりました!

リナックス先生

素晴らしい成長ね!手動の作業を自動化し、データの抽出をパイプで繋ぎ、AIに意味を解釈させ、Slackに投げる。この一連のシステムを自力で組み上げられたなら、あなたはもう一人前のインフラアーキテクトよ。さて、いよいよ次回は最終回。AIがインフラ構築の主役になりつつある今、エンジニアが生き残るために必要な「セキュリティとこれからの運用」について語り尽くすわよ。最後まで気を抜かずにね!

▼ AI監視システムを24時間稼働させるならVPSで ▼

安定稼働で自動化も安心
「おすすめVPS」

VPSランキングを見る

最新の自動化スキルを活かす
「ITエンジニア転職」

転職エージェントを見る

コメント