本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。
PowerShellとCIMを活用したマルチノード・システムヘルスチェック自動化
【導入:解決する課題】 複数台のWindowsサーバーに対する手動のヘルスチェックを排除し、CIMセッションを用いた並列スキャンにより障害検知の初動を数分から秒単位へ短縮します。
【設計方針と処理フロー】
従来のWMI(RPC/DCOM)ではなく、最新のWS-Managementプロトコルを利用するCIMコマンドレットを採用します。これにより、Firewallフレンドリーな通信と、CimSessionの使い回しによるオーバーヘッド削減を実現します。
graph TD
A[Start] --> B["Generate CimSession List"]
B --> C{"Session Check"}
C -->|Success| D["Parallel Fetch: OS/Disk/EventLog"]
C -->|Failure| E["Log Connection Error"]
D --> F["Format PS-CustomObject"]
F --> G["Export CSV/JSON"]
G --> H[Finish]
【実装:コアスクリプト】
以下は、PowerShell 7の並列処理(-Parallel)を考慮しつつ、標準的なCIM操作をカプセル化した実戦向けスクリプトです。
function Get-RemoteSystemHealth {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[string[]]$ComputerNames,
[int]$MaxEventLogs = 10
)
# セッションオプションの設定
$option = New-CimSessionOption -Protocol Wsman -ConnectTimeout (New-TimeSpan -Seconds 10)
# 並列処理の実行 (PowerShell 7.x 推奨、5.1の場合はForEach-Objectで代替)
$results = $ComputerNames | ForEach-Object -Parallel {
$comp = $_
try {
# セッションの確立
$session = New-CimSession -ComputerName $comp -SessionOption $using:option -ErrorAction Stop
# 1. OS情報の取得 (稼働時間算出)
$os = Get-CimInstance -CimSession $session -ClassName Win32_OperatingSystem
$uptime = (Get-Date) - $os.LastBootUpTime
# 2. ディスク空き容量 (Cドライブ)
$disk = Get-CimInstance -CimSession $session -Query "SELECT FreeSpace, Size FROM Win32_LogicalDisk WHERE DeviceID = 'C:'"
# 3. 直近のエラーイベントログ
$logs = Get-CimInstance -CimSession $session -Query "SELECT Message, EventID, SourceName FROM Win32_NTLogEvent WHERE Logfile = 'System' AND Type = 'Error'" |
Select-Object -First $using:MaxEventLogs
# データ集約
[PSCustomObject]@{
PSComputerName = $comp
Status = "Success"
UptimeDays = [Math]::Round($uptime.TotalDays, 2)
FreeSpaceGB = [Math]::Round($disk.FreeSpace / 1GB, 2)
DiskUsage = "{0:P2}" -f (1 - ($disk.FreeSpace / $disk.Size))
RecentErrors = ($logs.Message -join "; ")
Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
}
}
catch {
[PSCustomObject]@{
PSComputerName = $comp
Status = "Failed: $($_.Exception.Message)"
UptimeDays = $null
FreeSpaceGB = $null
DiskUsage = $null
RecentErrors = $null
Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
}
}
finally {
if ($session) { Remove-CimSession $session }
}
} -ThrottleLimit 10
return $results
}
# 実行例
# $report = Get-RemoteSystemHealth -ComputerNames "SRV-01", "SRV-02"
# $report | Export-Csv -Path "./HealthReport.csv" -NoTypeInformation -Encoding utf8
【検証とパフォーマンス評価】
計測手法:
Measure-Command { Get-RemoteSystemHealth -ComputerNames (1..50 | % { "Target-$_" }) }期待値:
逐次処理(PS 5.1): 約120〜180秒(タイムアウト待ちを含む)。
並列処理(PS 7.x
-Parallel): 約15〜30秒。
スケーラビリティ: 100台を超える環境では
-ThrottleLimitを調整し、ドメインコントローラーへの同時認証負荷を分散させる必要があります。
【運用上の落とし穴と対策】
PowerShell 5.1 vs 7:
- 5.1環境では
ForEach-Object -Parallelが存在しません。代わりにWorkflow(非推奨) か、軽量なRunspacesを利用する、あるいは外部モジュールThreadJobの検討が必要です。
- 5.1環境では
WinRMの有効化と認証:
Enable-PSRemotingが必須。また、ワークグループ環境ではTrustedHostsの設定や、Kerberos認証(AD環境)の利用を確認してください。
WMIクエリのコスト:
SELECT *は避け、必要なプロパティのみを明示的に指定することで、リモートノードのCPU負荷とネットワークトラフィックを削減します。
【まとめ】
CIMの優先利用: DCOM依存を排除し、ポート5985/5986(WS-Man)での運用を標準化する。
エラーハンドリングの徹底: 疎通不可を前提とした
try/catch設計により、スクリプトの停止を防ぐ。構造化データ出力:
PSCustomObjectで出力し、後続のCSV出力やDB登録を容易にする。

コメント