0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

JS7 チュートリアル:codex でログを自動解析しレポートを出すジョブ

0
Last updated at Posted at 2026-06-23

対象: JS7 の基本操作を一度触ったことがある人/運用自動化に興味がある人
題材: ワークフロー /ChatGPT_Worker/helloChatGPT のジョブ job-hello-ChatGPT
やること: WorkerNode01 の直近24時間ログを収集 → OpenAI codex (codex exec) で解析 → /home/user/ITOM に Markdown レポートを出力
前提環境: SETUP-mac-m4.md(Controller/JOC)+ WorkerNode01 に Agent 導入済み、かつ WorkerNode01 上で codex login 済み

このドキュメントは、実際に稼働しているジョブのシェルスクリプトを 1ブロックずつ読み解きながら
「何のために」「どう動くのか」を説明し、最後に 使い方(実行・確認・カスタマイズ) までまとめた解説記事です。

注: 本記事のホスト名・IPアドレス・認証情報はサンプル用の汎用値です。
(IP はドキュメント用レンジ 192.0.2.0/24 を使用。実環境の値に読み替えてください。)


0. 全体像(このジョブは何をするか)

JS7 Controller ──(指示)──> WorkerNode01 の Agent (http://192.0.2.10:4445)
                                   │
                                   ▼
        ┌──────────────────────────────────────────────────┐
        │ 1. 直近24時間のログを収集 (journalctl / 失敗時は /var/log)  │
        │ 2. 重要行を抽出して ~120KB に圧縮(トークン超過回避)         │
        │ 3. codex exec に「運用エンジニアとして解析せよ」と指示         │
        │ 4. /home/user/ITOM に Markdown レポートを書き出す            │
        │ 5. codex が失敗してもシェル集計版レポートを必ず生成           │
        └──────────────────────────────────────────────────┘
                                   │
                                   ▼
        /home/user/ITOM/report_<host>_<日時>.md         ← 解析レポート
        /home/user/ITOM/workernode01_logs_24h_<日時>.log ← 収集した生ログ

ポイントは 「ただのログ収集スクリプト」ではなく、生成AI(codex)に解析・要約・推奨アクション作成までやらせる こと。
人間が毎朝 journalctl を眺める代わりに、AIが日本語の運用レポートを書いてくれます。


1. 前提・準備

項目 内容
JOC Cockpit http://192.0.2.20:17446/joc/(初期 <JOC_USER> / <JOC_PASSWORD>
Controller ID jobscheduler
実行エージェント WorkerNode01(URL http://192.0.2.10:4445
必須ツール WorkerNode01 に codex CLI(または npx @openai/codex)が入っていること
認証 JS7 のジョブを実行する OS ユーザで codex login 済みであること(後述の「ハマりどころ」参照)
出力先 /home/user/ITOM(無ければ自動作成)

なぜ codex が必要か:このジョブは生ログを AI に渡して自然言語の運用レポートを作らせます。
codex が使えないと、後段の「フォールバック集計版」(grep ベースの簡易集計)に切り替わります。


2. スクリプト全体の構成

スクリプトは大きく 7つのパート に分かれています。

# パート 役割
0 PATH 解決 + codex 解決 JS7 特有の「ログインプロファイルを読まない」問題への対処
1 ログ収集 journalctl を主軸に、権限が無ければ /var/log へフォールバック
2 圧縮 重要行を優先抽出し、AIに渡すサイズを ~120KB に制限
3 フラグ検出 codex のバージョン差を --help で吸収
4 プロンプト組み立て AIへの指示文(章立て付き)を作る
5 codex 実行 解析を実行し、レポートを書き出す
6 検証+フォールバック 失敗時はシェル集計版レポートを必ず作る
7 後始末 一時ファイル削除と結果サマリー表示

以降、コードを引用しながら順に説明します。


3. パートごとの解説

冒頭:エラーで止まる安全設定

#!/usr/bin/env bash
set -euo pipefail
  • set -e … コマンドが失敗(非ゼロ終了)したらスクリプトを止める
  • set -u … 未定義変数を使ったらエラーにする(打ち間違い検出)
  • set -o pipefail … パイプ | の途中が失敗しても検知する

JS7 はジョブの終了コードで成功/失敗を判定します。set -euo pipefail
「気づかないうちに失敗していた」を防ぎます。ただし後半では一部わざと無効化します(理由は §3.6)。


パート0:PATH 解決と codex の発見

export PATH="/usr/local/bin:/usr/bin:/bin:$HOME/.local/bin:$HOME/.npm-global/bin:/usr/local/lib/node_modules/.bin:$PATH"
[ -s "$HOME/.nvm/nvm.sh" ] && export NVM_DIR="$HOME/.nvm" && . "$HOME/.nvm/nvm.sh" >/dev/null 2>&1 || true
for d in "$HOME"/.nvm/versions/node/*/bin; do [ -d "$d" ] && PATH="$d:$PATH"; done; export PATH

なぜ必要か: JS7 Agent はジョブを実行するとき、.bashrc.profile を読み込みません。
そのため、手で叩けば動く codexnode が、ジョブからは「コマンドが見つからない」になりがちです。
ここでは よくあるインストール先を明示的に PATH へ足しnvm(Node バージョン管理)配下の node も拾います。

CODEX="$(command -v codex || true)"
if [ -z "$CODEX" ] && command -v npx >/dev/null 2>&1; then CODEX="npx @openai/codex"; fi
if [ -z "$CODEX" ]; then echo "ERROR: codex/npx が PATH に見つかりません。PATH=$PATH" >&2; exit 127; fi
echo "[INFO] using codex: $CODEX"
  • まず codex 本体を探す
  • 無ければ npx @openai/codex(都度ダウンロード実行)にフォールバック
  • どちらも無ければ PATH を表示して終了コード127で停止(127=command not found の慣習)

|| true は「見つからなくてもここでは止めない」ためのおまじない(set -e 対策)。


出力先と作業ファイルの定義

HOST="$(hostname)"
TS="$(date +%Y%m%d_%H%M%S)"
OUTDIR="/home/user/ITOM"
mkdir -p "$OUTDIR"
RAW="$OUTDIR/workernode01_logs_24h_${TS}.log"   # 収集した生ログ
TRIM="$OUTDIR/.workernode01_trim_${TS}.log"     # codex 投入用に圧縮した抜粋
REPORT="$OUTDIR/report_${HOST}_${TS}.md"         # 最終レポート
CODEX_ERR="$OUTDIR/.codex_err_${TS}.log"
SINCE="24 hours ago"
  • TS(タイムスタンプ)をファイル名に入れることで、実行ごとに別ファイルになり履歴が残る
  • TRIMCODEX_ERR は先頭が . の隠しファイル(中間生成物)
  • SINCE="24 hours ago" … 収集期間。ここを変えれば対象期間を調整できる(§5 参照)

パート1:ログ収集(フォールバック付き)

if command -v journalctl >/dev/null 2>&1 && journalctl --since "$SINCE" -n 1 --no-pager >/dev/null 2>&1; then
    journalctl --since "$SINCE" --no-pager        # システム全体
    journalctl --since "$SINCE" -p err --no-pager # 優先度 err 以上だけ
    systemctl --failed --no-pager                 # 失敗したサービス
else
    # /var/log/syslog, auth.log, kern.log ... を tail
    # dmesg -T も取得
fi

設計の肝はフォールバック:

  • まず journalctl使えるか&権限があるか を実際に1行取得してテスト
  • 使えれば systemd ジャーナルを採用(最も網羅的)
  • 使えなければ /var/log 配下の主要ファイルと dmesg を採用

さらに JS7 Agent 自身のログも探して添付し、最後に df -h(ディスク)と free -h(メモリ)を記録します。

} > "$RAW" 2>>"$RAW" || true
RAW_LINES=$(wc -l < "$RAW" 2>/dev/null || echo 0)
  • { ... } > "$RAW" … 中括弧でまとめた全出力を1ファイルにまとめて書き出す
  • 標準エラーも 2>>"$RAW" で同じファイルに追記
  • || true で「収集中に一部失敗しても全体は止めない」

パート2:AIに渡すための圧縮

{
  echo "##### 重要行(error/fail/warn/critical 等を抽出, 最大3000行) #####"
  grep -iE 'error|fail|failed|warn|critic|fatal|panic|segfault|oom|out of memory|denied|refused|timeout|unreachable|reset|kill' "$RAW" | tail -n 3000
  echo "##### 全体の末尾(直近の流れ, 最大2000行) #####"
  tail -n 2000 "$RAW"
} > "$TRIM"

if [ "$(wc -c < "$TRIM")" -gt 120000 ]; then
  head -c 120000 "$TRIM" > "${TRIM}.cut" && mv "${TRIM}.cut" "$TRIM"
fi

なぜ圧縮するか: 生ログは数千〜数万行になり、そのまま AI に渡すと
トークン上限を超えて失敗したり、コストが膨らみます。そこで、

  1. grep異常を示すキーワードを含む行だけ抽出(最大3000行)
  2. + ログ全体の末尾2000行(直近の流れを把握するため)
  3. それでも大きければ 先頭120KBで切り詰め

「重要行+直近の流れ」に絞ることで、少ない入力でも見落としにくいバランスにしています。


パート3:codex のバージョン差を吸収

HELP="$($CODEX exec --help 2>&1 || true)"
OUTFLAG=""
echo "$HELP" | grep -q -- '--output-last-message' && OUTFLAG="--output-last-message $REPORT"
SBXFLAG=""
echo "$HELP" | grep -q -- '--skip-git-repo-check' && SBXFLAG="--skip-git-repo-check"

codex CLI はバージョンによって使えるオプションが違います。そこで codex exec --help を読んで、

  • --output-last-message <file>AIの最終回答だけをファイルに保存できるか
  • --skip-git-repo-check … git リポジトリ外でも実行を許可するフラグがあるか

実行時に自動判定します。これにより、新旧どちらの codex でも動きます。


パート4:プロンプト(AIへの指示文)

PROMPT="あなたは熟練のITインフラ運用エンジニアです。
... 直近24時間のシステムログ抜粋です。
このログを解析し、運用責任者がそのまま読める日本語の運用レポートを Markdown形式で出力してください。
...
# WorkerNode01 ログ解析レポート(直近24時間)
## 1. サマリー(正常 / 注意 / 警告 / 危険 の4段階で総合判定)
## 2. 検出されたエラー・警告(事象・推定原因・件数・代表ログ行 を表で)
## 3. サービス/デーモンの異常
## 4. セキュリティ関連事象
## 5. リソース状況
## 6. 推奨アクション(優先度 高/中/低)
...
-------------------- LOG START --------------------
$(cat "$TRIM")
--------------------- LOG END ---------------------"

これが このジョブの心臓部です。良いレポートを得るコツが詰まっています:

  • 役割を与える:「熟練のITインフラ運用エンジニアです」→ 回答の専門性が上がる
  • 章立てを固定:6章のテンプレを指定 → 毎回フォーマットが揃い、比較しやすい
  • 健全性を4段階で判定させる:パッと見で危険度が分かる
  • 前置き禁止:「了解しました等の挨拶は不要」→ そのままレポートとして保存できる
  • ログは LOG START / LOG END で挟む:どこからどこまでが解析対象かをAIに明示

カスタマイズの主戦場はここです。章立てや観点を書き換えれば、レポートの中身を自由に変えられます。


パート5:codex 実行

set +e
if [ -n "$OUTFLAG" ]; then
  $CODEX exec $SBXFLAG $OUTFLAG "$PROMPT" >/dev/null 2>"$CODEX_ERR"
  CRC=$?
else
  $CODEX exec $SBXFLAG "$PROMPT" >"$REPORT" 2>"$CODEX_ERR"
  CRC=$?
fi
set -e
  • set +eここだけ set -e を一時解除。codex が失敗しても即終了させず、後段で自分でフォローするため
  • --output-last-message が使える場合:AIの最終回答を直接 $REPORT に保存
  • 使えない場合:標準出力(stdout)を $REPORT にリダイレクトして代用
  • CRC=$? … codex の終了コードを記録(後段の判定に使う)
  • エラーは $CODEX_ERR に分離(レポートにエラーログが混ざらないように)

パート6:検証とフォールバック(重要)

if [ ! -s "$REPORT" ] || [ "$CRC" -ne 0 ]; then
  # codex が失敗 or 空 → grep ベースの簡易レポートを生成
  ERRC=$(grep -icE 'error|fail|failed|fatal|panic' "$RAW")
  WRNC=$(grep -icE 'warn|critic' "$RAW")
  {
    echo "# WorkerNode01 ログ解析レポート(直近24時間 / フォールバック集計版)"
    echo "## エラー/警告 件数 ..."
    echo "## エラー上位(出現頻度) ..."   # sort | uniq -c | sort -rn
    echo "## failed systemd ユニット ..."
  } > "$REPORT"
fi

ここが運用品質を支える部分です。 AI への依存は便利ですが、
ネットワーク断・認証切れ・モデル障害などで失敗することがあります。
そのときでも 「レポートが1個もできない」事態を避けるため、

  • [ ! -s "$REPORT" ] … レポートが空かどうか(-s =サイズ>0)
  • [ "$CRC" -ne 0 ] … codex が異常終了したか

のどちらかなら、grep / sort / uniq による機械集計レポートに切り替えます。
AIほど賢くはありませんが、「エラー件数」「頻出エラー」「failed ユニット」は確実に分かります。


パート7:後始末とサマリー

rm -f "$TRIM"
echo "[INFO] レポート : $REPORT"
echo "[INFO] 生ログ   : $RAW"
head -n 40 "$REPORT"
exit 0
  • 中間ファイル $TRIM を削除
  • 生成物の場所をログに出す(JOC のログ画面で確認しやすい)
  • レポート冒頭40行を表示して、JOC のジョブログだけで結果の雰囲気が分かるようにする
  • 最後は exit 0レポートさえ作れていればジョブは成功扱いにし、スケジュール運用を妨げない

4. 使い方

4-1. GUI(JOC Cockpit)で手動実行する

  1. ブラウザで http://192.0.2.20:17446/joc/ にログイン(<JOC_USER> / <JOC_PASSWORD>
  2. 左メニュー インベントリ/ChatGPT_Worker/helloChatGPT を開く
  3. ジョブ job-hello-ChatGPT のスクリプトを確認・編集できる
  4. 編集したら必ず 配置(Deploy) ボタンで反映(配置しないと Controller では動きません)
  5. ワークフローを右クリック →「オーダーを追加」→ now(すぐ実行)

4-2. 実行結果を確認する

  • JOC の 履歴 / ログ からジョブログを開くと、[INFO] レポート : ... の行で保存先が分かる
  • WorkerNode01 上で実物を確認:
ls -lt /home/user/ITOM/ | head
cat /home/user/ITOM/report_*_*.md | head -60

4-3. 定期実行(毎日自動でレポート)

このジョブは既存のスケジュール(ChatGPT_平日 カレンダー+「8時」スケジュール)に紐づけられます。
配置済みであれば、毎朝8時に自動でレポートが /home/user/ITOM に蓄積されていきます。


5. カスタマイズの勘どころ

変えたいこと 触る場所
解析対象の期間(例:直近7日) SINCE="24 hours ago""7 days ago"
レポートの章立て・観点 パート4の PROMPT 内のテンプレ
AIに渡すログ量(コスト・精度の調整) パート2の tail -n 3000 / tail -n 2000 / 120000(バイト上限)
出力先フォルダ OUTDIR="/home/user/ITOM"
別ホストにも流用 文中の WorkerNode01 / IP 表記と、対象ログの選び方を見直す

古いレポートを自動で消したい場合は、末尾に世代管理を追加する例:
find /home/user/ITOM -name 'report_*_*.md' -mtime +30 -delete


6. ハマりどころ(トラブルシュート)

症状 原因 対処
ERROR: codex/npx が PATH に見つかりません Agent が .bashrc を読まない/codex 未導入 WorkerNode01 に codex を入れ、パート0の PATH に実体の場所を追加
レポートが「フォールバック集計版」になる codex が失敗(認証切れ・ネット断・モデル障害) $CODEX_ERR/home/user/ITOM/.codex_err_*.log)を確認。ジョブ実行ユーザで codex login 済みか確認
ログがほぼ空 journalctl 権限不足で /var/log にもアクセス不可 実行ユーザを adm / systemd-journal グループに追加、または sudo 構成を検討
codex がトークン超過で失敗 ログが巨大 パート2の行数・バイト上限を下げる
ジョブは成功なのに中身が薄い 解析期間に異常が少ない(健全) 正常時はサマリーが「正常」になるのが期待動作

7. まとめ

このジョブは「ログ収集スクリプト」に 生成AI(codex)による解析・要約・推奨アクション を組み合わせた、
ITOM(IT運用管理)の自動化サンプルです。設計上の工夫は次の3点に集約されます。

  1. JS7 特有の環境問題に強い:PATH を明示し、codex のバージョン差も自動吸収
  2. AIに優しい入力:重要行を抽出・サイズ制限してトークン超過とコストを抑制
  3. 必ず成果物を残す:codex 失敗時もシェル集計版にフォールバックし、exit 0 で運用を止めない

関連ドキュメント:実測は総計 約6.4万トークンを消費

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?