PowerShellによるリモートPCのシステム診断:CIMと並列処理による高速監視自動化

Tech

{ “role”: “Senior PowerShell Engineer”, “design_patterns”: [“Parallel Processing”, “CIM-over-WSMan”, “Robust Error Handling”], “naming_convention”: “Verb-Noun”, “research_sources”: [“Microsoft Learn: Get-CimInstance”, “Microsoft Learn: Get-WinEvent”], “technical_focus”: “Enterprise scalability, standard cmdlet optimization” } 本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。

PowerShellによるリモートPCのシステム診断:CIMと並列処理による高速監視自動化

【導入:解決する課題】

多忙なシステム管理者が抱える「複数台のリモートPCに対する手動の死活確認やイベントログ確認」の工数を、標準コマンドレットのみを用いた並列スキャンにより最大90%削減します。

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

最新のPowerShell 7環境を想定し、ForEach-Object -Parallel による高速なスキャンを実現します。レガシーな Get-WmiObject (RPC) ではなく、Get-CimInstance (WS-Man) を採用することで、ファイアウォール親和性とパフォーマンスを両立させます。

graph TD
A[Start] --> B["コンピューターリストの読み込み"]
B --> C{"並列処理開始"}
C --> D["CIMセッションの確立試行"]
D --> E["システム情報取得: Win32_OperatingSystem"]
E --> F["特定イベントログ取得: Error/Critical"]
F --> G["結果のオブジェクト化"]
G --> H{"全台完了?"}
H -->|No| C
H -->|Yes| I["CSV/レポート出力"]
I --> J[Finish]

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

以下のスクリプトは、指定された複数のコンピューターから、OS情報、ディスク空き容量、および直近24時間に発生した「重大なエラーログ」を一括で取得します。

function Get-RemoteSystemHealth {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string[]]$ComputerNames,

        [int]$MaxEvents = 5,
        [int]$ThrottleLimit = 10
    )

    $results = $ComputerNames | ForEach-Object -Parallel {
        $comp = $_
        $report = [PSCustomObject]@{
            PSComputerName = $comp
            Status         = "Success"
            OSName         = $null
            FreeSpaceGB    = $null
            RecentErrors   = $null
            ErrorMessage   = $null
        }

        try {

            # CIMセッションオプション(タイムアウト設定)

            $option = New-CimSessionOption -ConnectTimeoutSec 5
            $session = New-CimSession -ComputerName $comp -SessionOption $option -ErrorAction Stop

            # 1. システム情報の取得

            $os = Get-CimInstance -CimSession $session -ClassName Win32_OperatingSystem
            $report.OSName = $os.Caption

            # 2. ディスク空き容量 (Cドライブ)

            $disk = Get-CimInstance -CimSession $session -Query "SELECT FreeSpace FROM Win32_LogicalDisk WHERE DeviceID = 'C:'"
            $report.FreeSpaceGB = [math]::Round($disk.FreeSpace / 1GB, 2)

            # 3. イベントログの取得 (直近24時間のエラー/重大)

            $filterHash = @{
                LogName      = 'System'
                Level        = 1, 2 # 1:Critical, 2:Error
                StartTime    = (Get-Date).AddDays(-1)
            }

            # リモートでのGet-WinEvent実行

            $events = Invoke-Command -Session (New-PSSession -ComputerName $comp) -ScriptBlock {
                param($f, $m)
                Get-WinEvent -FilterHashtable $f -MaxEvents $m -ErrorAction SilentlyContinue
            } -ArgumentList $filterHash, $using:MaxEvents

            $report.RecentErrors = ($events.Message -join " | ")

        } catch {
            $report.Status = "Failed"
            $report.ErrorMessage = $_.Exception.Message
        } finally {

            # セッションのクリーンアップ

            Get-CimSession -ComputerName $comp | Remove-CimSession
        }

        return $report
    } -ThrottleLimit $ThrottleLimit

    return $results
}

# 実行例


# $targetList = Get-Content "./pc_list.txt"


# Get-RemoteSystemHealth -ComputerNames $targetList | Out-GridView

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

  • 計測手法: Measure-Command を使用し、10台のリモートPCに対して逐次処理と並列処理(ThrottleLimit: 5)を比較。

  • 期待値:

    • 逐次処理:約60〜90秒(接続タイムアウト待ちを含む)。

    • 並列処理:約15〜20秒。

  • 大規模環境: 100台を超える環境では ThrottleLimit を30〜50に調整することで、ネットワーク負荷を抑えつつ数分以内にスキャンが完了します。

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

  1. WinRMの未有効化:

    • Get-CimInstance はデフォルトで WinRM (5985/5986) を使用します。接続できない場合は Enable-PSRemoting がターゲット側で必要です。
  2. PowerShell 5.1 と 7 の混在:

    • ForEach-Object -Parallel は PowerShell 7 以降の機能です。Windows PowerShell 5.1 環境では Start-Job または Workflow (非推奨) を検討する必要があります。
  3. ダブルホップ問題:

    • イベントログ取得時に別サーバーの参照が必要な場合、認証情報の委譲(CredSSP等)が必要になるケースがあります。本スクリプトではローカルログ取得に限定することで回避しています。

【まとめ】

  1. CIMを優先する: RPC依存のWMIコマンドレットを避け、モダンなCIMコマンドレットで通信を安定させる。

  2. 並列化で時短: ForEach-Object -Parallel を活用し、タイムアウト待ちによるボトルネックを解消する。

  3. 例外を握り潰さない: 接続失敗を catch し、どのPCがオフラインかを明確にレポートへ記録する。

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

コメント

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