WMI/CIMを活用したリモートPC一括監視とイベントログ抽出の自動化

Tech

<!-- [STYLE_PROMPT_CONVENTION]

  • Role: Senior PowerShell Engineer

  • Language: Japanese

  • Formatting: Markdown, Mermaid

  • Naming: Verb-Noun (PascalCase)

  • Principles: Standard Cmdlets, Error Handling, Parallelism, .NET Integration --> 本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。

    WMI/CIMを活用したリモートPC一括監視とイベントログ抽出の自動化

    【導入:解決する課題】

    数百台規模のリモートPCに対する手動のヘルスチェックを廃止し、OSの状態と特定エラーログをエージェントレスで高速に自動収集します。

    【設計方針と処理フロー】

    通信効率とセキュリティの観点から、レガシーなDCOM(WMI)ではなく、WS-Managementプロトコルを使用するCIMコマンドレット(Get-CimInstance)をベースに構築します。また、大規模環境での実行速度を確保するため、PowerShell 7.xの並列処理(ForEach-Object -Parallel)を採用します。

    graph TD
    A[Start] --> B["コンピューターリストの読み込み"]
    B --> C{"並列処理開始"}
    C --> D["CIMセッションの確立試行"]
    D -->|Success| E["OS情報/稼働時間の取得"]
    E --> F["特定イベントログの抽出"]
    F --> G["CIMセッションの破棄"]
    D -->|Failure| H["エラーログ記録"]
    G --> I["結果をカスタムオブジェクトに統合"]
    H --> I
    I --> J{"全ホスト終了?"}
    J -->|Yes| K["CSV/JSONレポート出力"]
    K --> L[Finish]
    

    【実装:コアスクリプト】

    以下は、リモート端末からOS情報(稼働時間含む)と、直近24時間のSystemログから「Error」を抽出する実戦的なスクリプトです。

    function Get-RemoteSystemHealth {
        [CmdletBinding()]
        param (
            [Parameter(Mandatory = $true)]
            [string[]]$ComputerNames,
    
            [Parameter()]
            [int]$MaxConcurrency = 10
        )
    
        # 並列処理によるデータ収集(PowerShell 7+ 推奨)
    
        $Results = $ComputerNames | ForEach-Object -Parallel {
            $Computer = $_
            $ErrorActionPreference = "Stop"
    
            $Report = [PSCustomObject]@{
                Timestamp    = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
                ComputerName = $Computer
                OSCaption    = $null
                LastBootUp   = $null
                UptimeDays   = $null
                ErrorLogs    = $null
                Status       = "Success"
                ErrorMessage = $null
            }
    
            try {
    
                # CIMオプションの設定(DCOMフォールバックが必要な場合はここで定義)
    
                $Option = New-CimSessionOption -Protocol Wsman -ConnectTimeoutSec 10
                $Session = New-CimSession -ComputerName $Computer -Option $Option
    
                # 1. OS基本情報と稼働時間の取得
    
                $OsInfo = Get-CimInstance -CimSession $Session -ClassName Win32_OperatingSystem
                $Report.OSCaption = $OsInfo.Caption
                $Report.LastBootUp = $OsInfo.LastBootUpTime
                $Report.UptimeDays = [Math]::Round(((Get-Date) - $OsInfo.LastBootUpTime).TotalDays, 2)
    
                # 2. 直近24時間のエラーイベント取得(Systemログ)
    
                $FilterTime = (Get-Date).AddDays(-1)
                $Events = Get-CimInstance -CimSession $Session -ClassName Win32_NTLogEvent `
                    -Filter "Logfile='System' AND Type='Error' AND TimeGenerated >= '$($FilterTime.ToString('yyyyMMddHHmmss.000000-000'))'"
    
                $Report.ErrorLogs = ($Events | ForEach-Object { "ID:$($_.EventCode) Source:$($_.SourceName)" }) -join " | "
    
                Remove-CimSession $Session
            }
            catch {
                $Report.Status = "Failed"
                $Report.ErrorMessage = $_.Exception.Message
            }
            finally {
                $Report
            }
        } -ThrottleLimit $MaxConcurrency
    
        return $Results
    }
    
    # --- 実行例 ---
    
    
    # $TargetList = Get-Content "C:\temp\PCList.txt"
    
    
    # $HealthReport = Get-RemoteSystemHealth -ComputerNames $TargetList
    
    
    # $HealthReport | Export-Csv -Path "./SystemHealthReport.csv" -NoTypeInformation -Encoding utf8
    

    【検証とパフォーマンス評価】

    100台のリモートPCに対して実行する場合、逐次処理(Sequential)ではネットワークタイムアウト待ちを含め数十分を要しますが、上記スクリプトの並列処理(-Parallel)を用いることで大幅に短縮可能です。

    • 計測例: Measure-Command { Get-RemoteSystemHealth -ComputerNames $testList }

    • 期待値: スロットル制限(MaxConcurrency)を適切に設定することで、逐次処理比で3倍〜5倍の高速化が期待できます。ただし、送信元PCのメモリ消費量と、ネットワーク帯域の飽和に注意が必要です。

    【運用上の落とし穴と対策】

    1. WinRMの有効化とFirewall: リモートPC側で Enable-PSRemoting が実行されており、TCP 5985 (HTTP) / 5986 (HTTPS) が許可されている必要があります。

    2. PowerShell 5.1 vs 7: ForEach-Object -Parallel は PowerShell 7 固有の機能です。Windows PowerShell 5.1 環境では Start-JobRunspaces を使用した書き換えが必要になります。

    3. ダブルホップ問題: リモートPCからさらに別のサーバーのリソースにアクセスする場合、Kerberos認証の委任設定(CredSSP等)が必要になります。今回のCIM取得のみであれば通常は不要です。

    4. WMIクエリのタイムアウト: イベントログが肥大化している場合、Win32_NTLogEvent へのクエリがタイムアウトすることがあります。-Filter 句で TimeGenerated をインデックスに基づき絞り込むことが必須です。

    【まとめ】

    1. CIMコマンドレットを優先: DCOMに依存する Get-WmiObject ではなく、Firewallフレンドリーな Get-CimInstance を使用すること。

    2. 並列処理の最適化: ネットワークの遅延時間を吸収するため、ForEach-Object -Parallel で同時接続数を制御しながら実行すること。

    3. 例外処理の徹底: 接続失敗やタイムアウトを Try-Catch で捕捉し、処理全体を止めないロギング戦略を構築すること。

ライセンス:本記事のテキスト/コードは特記なき限り CC BY 4.0 です。引用の際は出典URL(本ページ)を明記してください。
利用ポリシー もご参照ください。

コメント

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