ログ監視の自動化へ:FSOを極めて「システムを監視する力」を手に入れる
こんにちは。現場の設計と実装を渡り歩いてきた、あなたのエンジニアライフを支えるチーフアーキテクトです。
「マクロの記録」から一歩踏み出し、「自分でスクリプトを書いて、業務を自動化したい」――そう思ったあなたは、すでにエンジニアとしての正しい階段を登り始めています。素晴らしい一歩です。
しかし、単に「ファイルをコピーする」「フォルダを作る」といった操作だけでは、プロの現場で戦う武器としては少し足りません。真に価値のある自動化とは、「データを読み解き、状況を判断し、異常があれば報告する」という、いわば「思考」を伴うプロセスです。
今日は、VBScriptの心臓部とも言える`FileSystemObject` (FSO) を使い、膨大なログファイルの中から「致命的なエラー」を見つけ出し、閾値(しきい値)を超えたときだけアラートを出す、実戦的なログ解析スクリプトを一緒に構築していきましょう。
これをマスターすれば、あなたは「作業を自動化する人」から、「システムを監視する仕組みを作る人」へと進化できるはずです。
1. 設計図:ログ解析のメカニズム
いきなりコードを書き始めるのは、設計図なしにビルを建てるようなものです。まずは、私たちが作ろうとしているプログラムの「動き」を整理しましょう。
graph TD
A[開始] --> B[指定フォルダ内のログファイルを走査]
B --> C{ファイルはあるか?}
C -- Yes --> D[ファイルを1行ずつ読み込む]
D --> E{FATAL/WARNが含まれるか?}
E -- Yes --> F[カウントをインクリメント]
E -- No --> D
F --> D
C -- No --> G[終了]
D -- ファイル末尾に到達 --> H{カウント > 閾値?}
H -- Yes --> I[アラート用サマリーを出力]
H -- No --> G
I --> G
ここがエンジニアの視点
この設計の肝は、「ファイルを丸ごとメモリに読み込まない」ことです。
数GBもあるような巨大なログファイルを `ReadAll` メソッドで一気に読み込もうとすると、メモリを食いつぶしてスクリプトがクラッシュします。私たちは、`ReadLine` を使って「一行ずつ、慎重に」処理を進める、プロの作法を身につけます。
2. 実装:ログ解析エンジンの構築
それでは、魂を込めたコードを見ていきましょう。このスクリプトは、そのままコピーして、パスを書き換えるだけで動作するように設計しています。
' ==============================================================================
' Script Name: LogAnalyzerPro.vbs
' Description: ログファイルを走査し、FATAL/WARNの発生回数をカウント。
' 閾値を超えた場合にサマリーレポートを生成する。
' Author: Chief Architect
' ==============================================================================
Option Explicit ' 変数の強制宣言(これを行うだけでバグの8割は防げます)
' --- 設定エリア ---
Const TARGET_FOLDER = "C:\Logs\AppLogs\" ' 調査対象のフォルダ
Const REPORT_FILE = "C:\Logs\AlertReport.txt" ' 警告レポートの出力先
Const THRESHOLD_FATAL = 3 ' FATALの許容回数
Const THRESHOLD_WARN = 10 ' WARNの許容回数
' --- 変数宣言 ---
Dim fso, folder, file, ts
Dim fatalCount, warnCount
Dim lineContent, reportText
Dim isAlertTriggered
' オブジェクトの初期化
Set fso = CreateObject("Scripting.FileSystemObject")
' 1. フォルダの存在確認(ここを怠るとエラーで即死します)
If Not fso.FolderExists(TARGET_FOLDER) Then
MsgBox "エラー: 指定されたフォルダが存在しません: " & TARGET_FOLDER, vbCritical
WScript.Quit
End If
' カウンターの初期化
fatalCount = 0
warnCount = 0
isAlertTriggered = False
' 2. フォルダ内のファイル走査開始
Set folder = fso.GetFolder(TARGET_FOLDER)
For Each file In folder.Files
' 拡張子が .log のファイルのみを対象とする
If LCase(fso.GetExtensionName(file.Name)) = "log" Then
' ファイルを読み込みモードで開く
' 3 = ForReading (読み取り専用)
Set ts = file.OpenTextFile(1, 1)
' 3. ファイルを一行ずつ走査(メモリ節約の極意)
Do Until ts.AtEndOfStream
lineContent = ts.ReadLine
' キーワード判定 (InStr は大文字小文字を区別しない設定で使うのが定石)
If InStr(1, lineContent, "FATAL", vbTextCompare) > 0 Then
fatalCount = fatalCount + 1
ElseIf InStr(1, lineContent, "WARN", vbTextCompare) > 0 Then
warnCount = warnCount + 1
End If
Loop
ts.Close ' 開いたファイルは必ず閉じる(リソース解放の鉄則)
Set ts = Nothing
End If
Next
' 4. 閾値判定とレポート生成
If fatalCount >= THRESHOLD_FATAL Or warnCount >= THRESHOLD_WARN Then
isAlertTriggered = True
' レポート内容の組み立て
reportText = "【重要】ログ監視アラート" & vbCrLf & _
"発生日時: " & Now & vbCrLf & _
"------------------------------------" & vbCrLf & _
"FATAL検知数: " & fatalCount & " (閾値: " & THRESHOLD_FATAL & ")" & vbCrLf & _
"WARN 検知数: " & warnCount & " (閾値: " & THRESHOLD_WARN & ")" & vbCrLf & _
"------------------------------------" & vbCrLf & _
"至急、システム状況を確認してください。"
' レポートファイル書き出し (2 = ForWriting, True = 上書き作成)
Set ts = fso.CreateTextFile(REPORT_FILE, True)
ts.WriteLine(reportText)
ts.Close
MsgBox "警告! 閾値を超えました。レポートを確認してください。" & vbCrLf & REPORT_FILE, vbExclamation
Else
' 正常な場合は何もせず終了(あるいはログに記録)
' MsgBox "チェック完了: 異常なし", vbInformation
End If
' 5. 後片付け(オブジェクトのライフサイクル管理)
Set folder = Nothing
Set fso = Nothing
WScript.Echo "ログ解析プロセスが正常に完了しました。"
3. アーキテクトの解説:ここが「プロ」の分かれ道
コードをただ眺めるだけでは不十分です。なぜこのように書いたのか、その「意図」を理解してください。
① `Option Explicit` の威力
冒頭に書いたこの一行。これがないと、タイポ(打ち間違い)をして変数名が違っていても、VBScriptは「新しい変数だ」と勝手に解釈して実行を続けてしまいます。これが原因で、カウントが合わないといった「原因不明のバグ」が多発します。「変数は必ず宣言する」。これは鉄則です。
② `InStr` 関数による柔軟な検索
`If lineContent = “FATAL” Then` と書いてしまうと、行の中に「[ERROR] FATAL: System down」のように他の文字が含まれていた場合に検知できません。`InStr` を使うことで、文字列の「どこかに含まれているか」を判定できます。`vbTextCompare` を指定することで、大文字・小文字の揺れ(fatal / FATAL)も吸収できる、非常に堅牢な書き方です。
③ リソースのライフサイクル(重要!)
`ts.Close` を忘れていませんか? ファイルを開いたままにすると、そのファイルは「使用中」となり、他のプログラムや、次回のスクリプト実行がファイルを操作できなくなります。「開けたら閉じる」。これはOSとの約束事です。
④ エラーハンドリングの思想
今回のコードでは、最初に `fso.FolderExists` でフォルダの存在を確認しています。プロのスクリプトは、「想定外の事態」が起きたときに、エラーで止まるのではなく、「何が原因で止まったのか」をユーザーに優しく(かつ正確に)伝えるように設計します。
4. 陥りやすい罠(トラブルシューティング)
実務で運用する際、以下の2点には特に注意してください。
1. ファイルのロック問題
ログを出力しているアプリケーションがファイルを「排他的にロック」している場合、`OpenTextFile` でエラーが発生することがあります。その場合は、エラーハンドリング(`On Error Resume Next` を適切に使い、エラー時にリトライするかスキップするか決める)が必要になります。
2. 文字コードの壁
VBScriptのFSOは、標準では ANSI (Shift-JIS) を想定しています。もしログファイルが UTF-8 で保存されている場合、日本語が文字化けしたり、正しく判定できなかったりします。その場合は、`ADODB.Stream` オブジェクトという、さらに高度な道具を使う必要が出てきます。
最後に
お疲れ様でした。あなたは今、単なる「コードの書き手」ではなく、「システムの健全性を守るロジックの設計者」としての第一歩を踏み出しました。
このスクリプトは、あくまで基本形です。ここから「特定の時間帯だけ解析する」「メールで通知を送る」「解析結果をデータベースに書き込む」といった拡張が無限に可能です。
「なぜこう動くのか?」という問いを常に持ち続けてください。その積み重ねが、あなたを伝説的なエンジニアへと押し上げるのです。
また次の現場でお会いしましょう。応援していますよ!
