本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。
PowerShellクラスと並列処理によるスケーラブルなインベントリ収集基盤
【導入:解決する課題】 散在するサーバー情報の収集をクラス定義と並列処理で効率化し、型安全なデータ構造によって後続処理の保守性を極限まで高めます。(64文字)
【設計方針と処理フロー】 本設計では、PowerShell 5.0以降で導入された「クラス(Class)」を利用してデータのスキーマを定義します。従来のカスタムオブジェクト(PSCustomObject)に比べ、型の制約を課すことでデータの一貫性を担保し、大規模環境でのプロパティ欠損を防ぎます。
graph TD
A["開始"] --> B["インベントリクラスの定義"]
B --> C["ターゲットホストのリスト取得"]
C --> D["ForEach-Object -Parallel による並列実行"]
D --> E{"CIMセッション試行"}
E -->|成功| F["クラスインスタンスの生成と格納"]
E -->|失敗| G["エラーログの記録"]
F --> H["結果の集計・エクスポート"]
G --> H
H --> I["終了"]
並列処理には PowerShell 7.x 以降の ForEach-Object -Parallel を採用し、CIM (Common Information Model) インスタンス経由で効率的にシステム情報を取得します。
【実装:コアスクリプト】
# =================================================================
# 概要: PowerShellクラスを利用したサーバー情報収集スクリプト
# 要件: PowerShell 7.0以上推奨 (Parallel処理のため)
# =================================================================
# 1. データ構造の定義(再利用性の向上)
class ServerInventory {
[string]$ComputerName
[string]$OSCaption
[uint64]$TotalPhysicalMemoryGB
[datetime]$LastBootUpTime
[string]$Status
# コンストラクタ
ServerInventory([string]$name) {
$this.ComputerName = $name
$this.Status = "Unknown"
}
# メモリ換算メソッド
[void]SetMemory([uint64]$bytes) {
$this.TotalPhysicalMemoryGB = [math]::Round($bytes / 1GB, 2)
}
}
function Get-ServerAssetReport {
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)]
[string[]]$ComputerNames,
[Parameter()]
[int]$ThrottleLimit = 5
)
process {
# 並列処理の実行
$results = $ComputerNames | ForEach-Object -Parallel {
$comp = $_
$entry = [ServerInventory]::new($comp)
try {
# CIMを用いたOS情報の取得
$os = Get-CimInstance -ClassName Win32_OperatingSystem -ComputerName $comp -ErrorAction Stop
$cs = Get-CimInstance -ClassName Win32_ComputerSystem -ComputerName $comp -ErrorAction Stop
$entry.OSCaption = $os.Caption
$entry.SetMemory($cs.TotalPhysicalMemory)
$entry.LastBootUpTime = $os.LastBootUpTime
$entry.Status = "Success"
}
catch {
Write-Error "Failed to collect data from $comp: $($_.Exception.Message)"
$entry.Status = "Error: $($_.Exception.Message)"
}
# クラスオブジェクトをパイプラインへ戻す
$entry
} -ThrottleLimit $ThrottleLimit
return $results
}
}
# 実行例
# $targets = @("Server01", "Server02", "localhost")
# $report = Get-ServerAssetReport -ComputerNames $targets
# $report | Out-GridView
【検証とパフォーマンス評価】
Measure-Command を用いて、逐次処理と並列処理の比較検証を行います。
# 検証コード例
$testHosts = @("localhost") * 10 # 擬似的な負荷
$time = Measure-Command {
$res = Get-ServerAssetReport -ComputerNames $testHosts -ThrottleLimit 5
}
Write-Host "処理時間: $($time.TotalSeconds) 秒"
- 期待値: 100台規模の環境において、逐次処理(約5〜10分)に対し、スロットル制限5〜10の並列処理では約1〜2分程度まで短縮可能です。※ネットワーク遅延やRPCのタイムアウト設定に依存。
【運用上の落とし穴と対策】
PowerShell バージョンの壁:
ForEach-Object -Parallelは PowerShell 7 以降の機能です。Windows PowerShell 5.1 環境ではStart-JobやRunspacesへの書き換え、あるいはモジュール配布の検討が必要です。CIM/WinRM の到達性: ファイアウォール(TCP 5985/5986)がブロックされている場合、
Get-CimInstanceがタイムアウトします。事前にTest-NetConnectionでのポートチェックをフローに組み込むことを推奨します。シリアライズの制限: クラスオブジェクトを並列ブロック(scriptblock)から返す際、型情報が一部欠落(Deserialized)する場合があります。プロパティ参照には問題ありませんが、メソッドの再呼び出しが必要な場合は注意が必要です。
【まとめ】
クラス定義による型安全性の確保: 出力データの構造を明確にし、スキーマ崩れを防止する。
標準コマンドレットへの準拠: 依存関係を最小限にし、標準のCIM/CIMSessionを活用してOS負荷を抑える。
並列処理の適切な制御:
-ThrottleLimitを活用し、管理端末のCPUリソースとネットワーク負荷のバランスを最適化する。

