[Identity] Senior PowerShell Engineer (Windows/Linux Ops) [Focus] Remote Management, CIM/WMI, Parallel Processing, Scalability [Logic] WinRM Session -> CIM Instance Collection -> Event Filter -> Exception Handling -> Object Export [Status] Draft (Unverified)
本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。
PowerShell/CIMによるマルチノード・リモート死活監視とイベント収集の自動化
【導入:解決する課題】
複数拠点に点在するWindows端末の負荷状況と致命的なエラーログを一括取得し、管理者が1台ずつログインして確認する手間と工数を劇的に削減します。
【設計方針と処理フロー】
本スクリプトは、レガシーな Get-WmiObject (RPC) ではなく、モダンな Get-CimInstance (WS-Man) を採用します。これにより、ファイアウォール親和性を高め、ForEach-Object -Parallel による高速な並列スキャンを実現します。
graph TD
A[Start] --> B["Target Computer List"]
B --> C{"Parallel Execution?"}
C -->|Yes| D[New-CimSession]
D --> E["Query: Win32_OperatingSystem / LogicalDisk"]
E --> F["Query: Win32_NTLogEvent / Get-WinEvent"]
F --> G["Error Handling / Logging"]
G --> H["Consolidate Results"]
H --> I[Finish]
CIMセッションを事前に確立することで、複数のクエリを単一のコネクションで実行し、オーバーヘッドを最小化する設計です。
【実装:コアスクリプト】
以下は、PowerShell 7.x 以上の並列処理機能を前提とした、実戦的な監視スクリプトのテンプレートです。
function Get-RemoteSystemHealth {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[string[]]$ComputerNames,
[int]$MaxConcurrency = 10,
[int]$EventHours = 24
)
$ComputerNames | ForEach-Object -Parallel {
$Computer = $_
$Result = [PSCustomObject]@{
ComputerName = $Computer
Timestamp = Get-Date
OSStatus = "Failed"
FreeDiskGB = $null
CriticalLogs = 0
ErrorMessage = $null
}
try {
# CIMセッションの確立(WinRM)
$SessionOption = New-CimSessionOption -Protocol Wsman -ConnectTimeoutMS 5000
$Session = New-CimSession -ComputerName $Computer -SessionOption $SessionOption -ErrorAction Stop
# OS情報の取得(稼働時間・メモリ)
$OS = Get-CimInstance -CimSession $Session -ClassName Win32_OperatingSystem
# ディスク情報の取得(Cドライブの空き容量)
$Disk = Get-CimInstance -CimSession $Session -Query "SELECT FreeSpace FROM Win32_LogicalDisk WHERE DeviceID = 'C:'"
# イベントログの取得(過去N時間のSystemログ: Error/Criticalのみ)
$FilterHash = @{
LogName = 'System'
Level = 1, 2 # 1:Critical, 2:Error
StartTime = (Get-Date).AddHours(-$using:EventHours)
}
# CIMセッション経由でGet-WinEventを実行
$Events = Get-WinEvent -FilterHashtable $FilterHash -ComputerName $Computer -ErrorAction SilentlyContinue
# オブジェクトの組み立て
$Result.OSStatus = "Healthy"
$Result.FreeDiskGB = [Math]::Round($Disk.FreeSpace / 1GB, 2)
$Result.CriticalLogs = if ($Events) { $Events.Count } else { 0 }
} catch {
$Result.ErrorMessage = $_.Exception.Message
} finally {
if ($Session) { Remove-CimSession $Session }
$Result
}
} -ThrottleLimit $MaxConcurrency
}
# 実行例
# $Targets = Get-Content "C:\Path\To\Servers.txt"
# $Report = Get-RemoteSystemHealth -ComputerNames $Targets
# $Report | Export-Csv -Path ".\SystemHealthReport.csv" -NoTypeInformation -Encoding utf8
【検証とパフォーマンス評価】
100台のリモートPCに対し、逐次(Sequential)処理と並列(Parallel)処理で実行時間を比較した場合の期待値は以下の通りです。
逐次処理: 約300秒〜500秒(1台あたり3〜5秒のタイムアウト待ちを含むため)
並列処理 ($MaxConcurrency = 20): 約30秒〜50秒
評価:
Get-CimInstanceはNew-CimSessionを再利用することで、同一ホストへの複数問い合わせを高速化できます。また、Get-WinEventのFilterHashtableは、クライアント側ではなくサーバ側でフィルタリングを行うため、ネットワークトラフィックを大幅に抑制します。
【運用上の落とし穴と対策】
WinRMの未有効化: リモート実行には
Enable-PSRemotingが必須です。GPOによる一括設定が推奨されます。PowerShell 5.1の互換性:
ForEach-Object -Parallelは PS 7以降の機能です。PS 5.1環境ではStart-JobやRunspacesを使用するか、逐次処理に変更する必要があります。ダブルホップ問題: 取得したログをさらに別の共有フォルダに保存する場合など、資格情報の委譲(CredSSP)が必要になるケースがあります。
時刻同期:
StartTimeを指定する際、操作端末とリモート端末の時刻がズレていると、正確なログ範囲を取得できないため、NTP同期が前提となります。
【まとめ】
CIMへの移行: RPC(WMI)を避け、WinRM(CIM)を利用してセキュリティと透過性を確保する。
サーバーサイドフィルタ:
FilterHashtableを活用し、必要なデータのみを最小限のトラフィックで取得する。並列化の制御:
ThrottleLimitを適切に設定し、管理端末側のリソース枯渇を防ぐ。


コメント