【実務・中級編】【上級プロフェッショナル向け】robocopy実行ログをFSOでリアルタイム監視しエラー転送のみを即時ピックアップする解析エンジン – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク
スポンサーリンク

ログ監視の素人とプロフェッショナルの境界線: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)を深く理解し、リソースのライフサイクルを制御下に置くことができれば、これほど軽量で強力な監視エンジンは他にない。

「動けばいい」スクリプトを書くのは誰にでもできる。しかし、「低負荷で、堅牢で、スケーラブルな」エンジンを設計できる者こそが、真の自動化エンジニアである。この設計思想を、貴殿の次なるプロジェクトに昇華させてほしい。

タイトルとURLをコピーしました