ログ監視の素人とプロフェッショナルの境界線:FSOによるrobocopyリアルタイム解析エンジンの設計思想
業務自動化の現場において、「バックアップが成功したか」を確認するのは初歩中の初歩だ。真にプロフェッショナルが求められるのは、「数百万のファイルが動く巨大なバックアッププロセスの中で、どのファイルが、なぜ、いつ失敗したのか」を、システム負荷を最小限に抑えつつ、ミリ秒単位の遅延で検知する仕組みを構築することである。
多くの開発者が陥る致命的なミスがある。それは、増大し続けるログファイルを、定期的に `ReadAll` で丸ごと読み込み、全行をループで走査するという、リソースを食いつぶす「力技」だ。ログファイルが数GBに達した瞬間、そのスクリプトはI/O負荷の爆弾となり、監視対象のシステムそのものを停止させかねない。
本稿では、FileSystemObject (FSO) を使い、ファイルの末尾(EOF)を追跡し続ける「Tail-Follow」方式の設計、およびrobocopyの出力特性を突いたエラー抽出エンジンの実装方法を伝授する。
1. 設計思想:なぜ「全件走査」は悪なのか
ログ監視における設計の要諦は、「既読領域を二度と読み込まない」ことにある。
非効率な設計(アンチパターン)
1. 5秒ごとにログファイルを開く。
2. `ReadAll` で全内容をメモリに展開する。
3. 前回の実行時と差分があるか比較する。
4. 差分を解析する。
この設計では、ログの増大とともにメモリ消費量とCPU使用率が指数関数的に増大する。これは「スケーラビリティ」の欠如であり、エンタープライズ環境では許されない。
プロフェッショナルの設計(テイル・フォロー方式)
1. ログファイルを開き、一度 `AtEndOfStream`(ファイルの末尾)までシークする。
2. ループ内で「新しい行」があるかのみを確認する。
3. 新しい行があれば、`ReadLine` でその行だけを読み込み、解析する。
4. 指針(ポインタ)を維持したまま、次の行を待機する。
これにより、メモリ消費は常に「最新の数行分」に抑えられ、I/O負荷は極めて軽微なものとなる。
2. 実装:robocopy リアルタイム・エラー・トラッカー
以下に、実務に耐えうる堅牢なVBScriptコードを示す。このコードは、単なるログ読み取りではなく、エラーパターンの抽出とアラートログへの書き出しを統合した「解析エンジン」として設計している。
' ==============================================================================
' Module: RobocopyRealTimeAnalyzer
' Description: robocopyのログをリアルタイム監視し、エラー行を抽出する
' Author: Chief Architect
' ==============================================================================
Option Explicit
' --- 定数定義 (保守性を高めるため、マジックナンバーを排除) ---
Const LOG_FILE_PATH = "C:\Backup\logs\robocopy_run.log"
Const ALERT_LOG_PATH = "C:\Backup\logs\error_alerts.log"
Const CHECK_INTERVAL_MS = 1000 ' 監視間隔 (ms)
Const ERROR_PATTERN = "ERROR" ' robocopyの出力から特定するエラーキーワード
' --- メインルーチン ---
Sub Main()
Dim fso, logFile, alertFile
Dim strLine, lastPos
Set fso = CreateObject("Scripting.FileSystemObject")
' ログファイルの存在確認
If Not fso.FileExists(LOG_FILE_PATH) Then
WScript.Echo "Error: Target log file not found: " & LOG_FILE_PATH
WScript.Quit 1
End If
WScript.Echo "Monitoring started: " & LOG_FILE_PATH
' 1. ログファイルを「読み取り専用」で開く
' 2. 最初はファイルの末尾に移動し、これ以降の更新のみを対象とする
Set logFile = fso.OpenTextFile(LOG_FILE_PATH, 1) ' 1 = ForReading
logFile.AtEndOfStream = True ' ファイルの末尾へシーク
' アラートログ用のストリームを準備
Set alertFile = fso.OpenTextFile(ALERT_LOG_PATH, 8, True) ' 8 = ForAppending
' 無限ループによるリアルタイム監視
Do While True
' ファイルの末尾に達していないかチェック
If Not logFile.AtEndOfStream Then
' 新しい行を読み込む
strLine = logFile.ReadLine
' エラーパターンの解析
If AnalyzeLine(strLine) Then
' エラー発見時のアクション
WriteAlert alertFile, strLine
End If
Else
' 新しい書き込みがない場合は待機 (CPU負荷軽減のために必須)
WScript.Sleep CHECK_INTERVAL_MS
End If
' ※注: 実際のプロダクション環境では、ここでログのローテーション(ファイルのリセット)を
' 検知するロジックを組み込むのが理想的である。
Loop
' クリーンアップ (このコードは無限ループのため到達しないが、設計上重要)
logFile.Close
alertFile.Close
Set logFile = Nothing
Set alertFile = Nothing
Set fso = Nothing
End Sub
' --- 解析エンジン ---
' 渡された行がエラーに該当するかを判定する
Function AnalyzeLine(ByVal line)
AnalyzeLine = False
' InStrは高速。正規表現(RegExp)が必要なほど複雑なパターンの場合は
' CreateObject("VBScript.RegExp") を検討せよ。
If InStr(1, line, ERROR_PATTERN, vbTextCompare) > 0 Then
AnalyzeLine = True
End If
End Function
' --- アラート出力エンジン ---
' 抽出されたエラーを専用ログへ記録する
Sub WriteAlert(ByRef alertFile, ByVal errorLine)
Dim timestamp
timestamp = Now ' 発生時刻の付与
' ログへの書き出し
alertFile.WriteLine "[" & timestamp & "] ALERT: " & errorLine
' コンソールへの出力 (デバッグ用)
WScript.Echo "!!! ERROR DETECTED: " & errorLine
End Sub
' --- エントリポイント ---
Main
3. アーキテクトの視点:プロダクション運用における3つの警告
このスクリプトを実戦投入する前に、以下の「設計上の注意点」を脳裏に刻んでおいてほしい。
① ファイル・ロッキング(File Locking)への対処
`robocopy` がログファイルに書き込みを行っている最中、FSOでファイルを開こうとすると、アクセス拒否(Permission Denied)が発生する可能性がある。
上記のコードでは `OpenTextFile(…, 1)` (読み取り専用)を使用しているが、それでもrobocopy側が排他的ロックをかけている場合はエラーとなる。
解決策: `On Error Resume Next` でエラーをトラップし、アクセスできない場合は数秒待機してリトライする「リトライ・メカニズム」を実装するのがプロの作法だ。
② ログ・ローテーションの罠
監視対象のログファイルが、日付が変わるタイミングなどで「切り捨て(Truncate)」されたり、「新しいファイルにリネーム」されたりする場合、現在の `TextStream` オブジェクトは「存在しない古いファイル」の末尾を指し続けることになる。
解決策: ループ内で `fso.GetFile(LOG_FILE_PATH).DateLastModified` を監視し、ファイルの更新日時が現在のオブジェクトの開いた日時より古い、あるいはファイルサイズが急激に小さくなった場合は、一度オブジェクトを `Close` して再生成するロジックを組み込め。
③ CPU使用率の制御
`Do While True` の中で `WScript.Sleep` を入れ忘れることは、エンジニアとしての自殺行為である。
`Sleep` がなければ、このスクリプトは1コアのCPUリソースを100%占有し続ける。`CHECK_INTERVAL_MS` は、業務要件(リアルタイム性の要求レベル)に応じて、1000ms〜5000msの間で最適化せよ。
まとめ
VBScriptは古い言語だ。しかし、そのオブジェクトモデル(FSO)を深く理解し、リソースのライフサイクルを制御下に置くことができれば、これほど軽量で強力な監視エンジンは他にない。
「動けばいい」スクリプトを書くのは誰にでもできる。しかし、「低負荷で、堅牢で、スケーラブルな」エンジンを設計できる者こそが、真の自動化エンジニアである。この設計思想を、貴殿の次なるプロジェクトに昇華させてほしい。
