今回は、複数のWindowsサーバーからsysteminfoコマンドで取得したシステム情報をPowerShellで効率的にパース・集約・分析する方法について、詳しく解説します。systeminfoコマンドは、OSバージョン・ハードウェア構成・ネットワーク情報などを一度に取得できる便利なツールですが、出力形式が非構造化テキストであるため、大規模な一元管理には工夫が必要です。
PowerShellのテキスト解析機能を活用すれば、複数のサーバーからsysteminfoを一括実行し、結果をCSV形式で出力・整理できます。本記事では、systeminfoの解析から一元化管理・レポート生成まで、実務的なスクリプトテンプレートを交えて解説します。
systeminfoコマンドの基本とデータ構造
systeminfoコマンド実行と基本出力
# ローカルコンピューターのシステム情報を表示
systeminfo
# リモートコンピューターの情報を取得
systeminfo /s remote-host /u domain\username /p password
systeminfoの出力は、以下の形式で構成されています:
ホスト名: SERVER001
OS 名: Microsoft Windows Server 2022 Standard
OS バージョン: 21H2
システム起動時刻: 2026/3/1 10:30:45
システムメーカー: Dell Inc.
システム モデル: PowerEdge R650
プロセッサ: Intel(R) Xeon(R) Platinum 8380 CPU
RAM(物理メモリ): 65536 MB
システム ロケール: ja;日本語
タイム ゾーン: 東京標準時
利用可能な物理メモリ: 32768 MB
仮想メモリ(最大サイズ): 131072 MB
出力形式の特徴
- 日本語キー名(環境に応じて英語の場合もあり)
- コロン(:)で区切られた キー:値 の形式
- 複数行を集約した情報(複数のネットワークアダプターなど)
systeminfoの出力を取得・フォーマット化
基本的なパース方法
パースとは、テキストなどの非構造化データを、プログラムが扱いやすい構造化データに分解・解析する処理のことです。
たとえばsysteminfoの出力は人間が読むための文字列ですが、このままではPowerShellから「ホスト名だけ取り出す」「メモリ量でソートする」といった処理ができません。パース処理を行うことで、キーと値に分解され、プログラムから簡単に扱えるデータになります。
systeminfoをテキスト形式で取得し、PowerShellで解析する基本的な手順:
# ローカルホストの systeminfo を取得
$systeminfo = systeminfo | Out-String
# または、リモートホストから取得
$systeminfo = & {
$params = @{
ComputerName = 'remote-host'
ScriptBlock = { systeminfo }
}
Invoke-Command @params | Out-String
}
ハッシュテーブルへの変換
テキスト形式のsysteminfoを構造化データ(ハッシュテーブル)に変換することで、検索・フィルタリングが容易になります。
# systeminfo 出力をハッシュテーブルに変換する関数
function Parse-SystemInfo {
param([string]$SysInfo)
$hashtable = @{}
# コロンで分割して キー:値 の対を抽出
$lines = $SysInfo -split "`n" | Where-Object { $_ -match ':' }
foreach ($line in $lines) {
$key, $value = $line -split ':', 2
$key = $key.Trim()
$value = $value.Trim()
# キーをPowerShell向けに整形(スペースをアンダースコアに)
$cleanKey = $key -replace '\s+', '_' -replace '\(.*?\)', ''
$hashtable[$cleanKey] = $value
}
return $hashtable
}
# 使用例
$parsed = Parse-SystemInfo -SysInfo $systeminfo
Write-Host "ホスト名: $($parsed['ホスト名'])"
Write-Host "OS名: $($parsed['OS_名'])"
PowerShellによるテキストパース方法
正規表現を使用した詳細なパース
より正確なパースを実現するため、正規表現を活用します。
# systeminfo から特定項目を抽出
function Extract-SystemInfoField {
param(
[string]$SysInfo,
[string]$FieldName
)
# 正規表現で指定フィールドを検索
$pattern = "^$FieldName\s*:\s*(.*)$"
$match = $SysInfo | Select-String -Pattern $pattern -CaseSensitive
if ($match) {
return ($match.Matches.Groups[1].Value).Trim()
}
return $null
}
# 使用例
$hostname = Extract-SystemInfoField -SysInfo $systeminfo -FieldName "ホスト名"
$osVersion = Extract-SystemInfoField -SysInfo $systeminfo -FieldName "OS バージョン"
$ram = Extract-SystemInfoField -SysInfo $systeminfo -FieldName "RAM(物理メモリ)"
複数行の情報を抽出
ネットワークアダプターなど、複数行に渡る情報の抽出:
# ネットワークアダプター情報を抽出
function Extract-NetworkAdapters {
param([string]$SysInfo)
$adapters = @()
# ネットワークアダプター情報は複数行に渡るため、
# 「ネットワーク アダプター」で始まる行をグループ化
$lines = $SysInfo -split "`n"
$currentAdapter = @{}
foreach ($line in $lines) {
if ($line -match "^ネットワーク アダプター") {
if ($currentAdapter.Count -gt 0) {
$adapters += $currentAdapter
}
$currentAdapter = @{ Name = $line -replace ".*?: " }
}
elseif ($line -match "^\s+" -and $currentAdapter.Count -gt 0) {
# インデント付き行はネットワークアダプターの詳細
$key, $value = $line -split ':', 2
$currentAdapter[$key.Trim()] = $value.Trim()
}
}
return $adapters
}
複数サーバーからの情報一括取得
複数ホストのsysteminfoを並列実行
大規模環境では、複数ホストからの情報取得を並列化することで、処理時間を大幅に削減できます。
# 複数ホストから systeminfo を並列実行
$servers = @("server1", "server2", "server3", "server4")
$results = $servers | ForEach-Object -Parallel {
$hostname = $_
try {
$sysinfo = & {
$params = @{
ComputerName = $hostname
ScriptBlock = { systeminfo }
ErrorAction = 'Stop'
}
Invoke-Command @params | Out-String
}
[PSCustomObject]@{
Hostname = $hostname
Status = "成功"
SystemInfo = $sysinfo
}
}
catch {
[PSCustomObject]@{
Hostname = $hostname
Status = "失敗"
Error = $_.Exception.Message
}
}
} -ThrottleLimit 4 # 同時実行数は4に制限
$results | Format-Table Hostname, Status
Invoke-Commandの活用
リモートコンピューターからsysteminfoを実行する場合、Invoke-Commandを使用します。ただし、WinRM(Windows Remote Management)が有効化されていることが前提です。
# WinRM の確認と有効化
Enable-PSRemoting -SkipNetworkProfileCheck -Force
# リモート実行(認証が必要な場合)
$credential = Get-Credential
$sysinfo = Invoke-Command -ComputerName 'remote-host' `
-Credential $credential `
-ScriptBlock { systeminfo }
CSV形式での出力・データ分析
構造化データをCSVに出力
パースしたシステム情報をPSCustomObjectに変換し、CSVで出力:
# 複数ホストの情報をCSVで出力
function Export-SystemInfoToCSV {
param(
[string[]]$Servers,
[string]$OutputPath = "systeminfo_report.csv"
)
$report = @()
foreach ($server in $Servers) {
try {
$sysinfo = Invoke-Command -ComputerName $server `
-ScriptBlock { systeminfo } | Out-String
# 主要項目を抽出
$obj = [PSCustomObject]@{
Hostname = $server
OS = Extract-SystemInfoField -SysInfo $sysinfo -FieldName "OS 名"
OSVersion = Extract-SystemInfoField -SysInfo $sysinfo -FieldName "OS バージョン"
ProcessorCount = Extract-SystemInfoField -SysInfo $sysinfo -FieldName "プロセッサ"
TotalMemoryMB = Extract-SystemInfoField -SysInfo $sysinfo -FieldName "RAM(物理メモリ)"
AvailableMemoryMB = Extract-SystemInfoField -SysInfo $sysinfo -FieldName "利用可能な物理メモリ"
LastBootTime = Extract-SystemInfoField -SysInfo $sysinfo -FieldName "システム起動時刻"
ReportDate = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
}
$report += $obj
}
catch {
Write-Warning "ホスト $server の情報取得に失敗しました:$($_.Exception.Message)"
}
}
# CSV にエクスポート
$report | Export-Csv -Path $OutputPath -Encoding UTF8 -NoTypeInformation
Write-Host "レポートを $OutputPath に保存しました"
}
# 使用例
Export-SystemInfoToCSV -Servers @("server1", "server2", "server3")
メモリ搭載量でのグループ化・ソート
# CSVから読み込み、メモリ量でソート
$data = Import-Csv -Path "systeminfo_report.csv"
# メモリ量を数値に変換してソート
$sorted = $data | ForEach-Object {
$_.TotalMemoryMB = [int]$_.TotalMemoryMB
$_
} | Sort-Object TotalMemoryMB -Descending
# メモリ不足のサーバーを検出
$lowMemory = $sorted | Where-Object {
[int]$_.TotalMemoryMB -lt 32768 # 32GB未満
}
Write-Host "メモリが32GB未満のサーバー:"
$lowMemory | Format-Table Hostname, TotalMemoryMB
特定情報の抽出・検査
OSバージョンの不一致検出
# すべてのサーバーのOS バージョンを確認
$data = Import-Csv -Path "systeminfo_report.csv"
# バージョンごとにグループ化
$grouped = $data | Group-Object OSVersion | Select-Object Name, Count
Write-Host "OS バージョン分布:"
$grouped | Format-Table Name, Count
# 最新バージョンでないサーバーを検出
$outdated = $data | Where-Object { $_.OSVersion -ne "21H2" }
Write-Host "21H2 以外のサーバー:"
$outdated | Format-Table Hostname, OSVersion
システム起動時刻から稼働期間を計算
# 起動時刻から稼働日数を計算
$data = Import-Csv -Path "systeminfo_report.csv"
$data | ForEach-Object {
$bootTime = [datetime]::ParseExact($_.LastBootTime, "yyyy/M/d H:mm:ss", $null)
$uptime = (Get-Date) - $bootTime
[PSCustomObject]@{
Hostname = $_.Hostname
BootTime = $bootTime
UptimeDays = $uptime.Days
UptimeHours = $uptime.Hours
}
} | Sort-Object UptimeDays | Format-Table Hostname, BootTime, UptimeDays, UptimeHours
定期的なシステム情報の監視・トレンド分析
# 月次でシステム情報を取得・保存
$reportDate = Get-Date -Format "yyyyMM"
$outputPath = "reports\systeminfo_$reportDate.csv"
Export-SystemInfoToCSV -Servers (Get-Content servers.txt) -OutputPath $outputPath
# 複数月のデータを比較
$march = Import-Csv "reports\systeminfo_202603.csv"
$april = Import-Csv "reports\systeminfo_202604.csv"
# メモリ増加傾向を検出
Compare-Object -ReferenceObject $march -DifferenceObject $april `
-Property Hostname, TotalMemoryMB | Format-Table
運用効率化のためのスクリプト活用
自動化スクリプトのスケジューリング
Windows Task Schedulerを使用して、定期的(例:毎月1日)にスクリプトを実行:
# PowerShellスクリプトをタスクスケジューラに登録
$action = New-ScheduledTaskAction -Execute 'powershell.exe' `
-Argument '-File C:\scripts\collect-systeminfo.ps1'
$trigger = New-ScheduledTaskTrigger -Monthly -DaysOfMonth 1 -At 2am
Register-ScheduledTask -TaskName 'MonthlySystemInfoCollection' `
-Action $action -Trigger $trigger -User 'SYSTEM' -RunLevel Highest
エラーハンドリング・ログ出力
# スクリプト実行時のログ記録
$logPath = "C:\logs\systeminfo_$(Get-Date -Format yyyyMMdd).log"
try {
Export-SystemInfoToCSV -Servers (Get-Content servers.txt) `
-OutputPath "systeminfo_report.csv"
Add-Content -Path $logPath -Value "$(Get-Date): 成功"
}
catch {
Add-Content -Path $logPath -Value "$(Get-Date): 失敗 - $($_.Exception.Message)"
}
まとめ
systeminfoコマンドとPowerShellを組み合わせることで、複数のWindowsサーバーのシステム情報を効率的に一元管理できます。テキストパース・並列実行・CSV出力などの機能を活用すれば、運用業務の自動化・効率化が実現できます。
本記事で解説したスクリプトテンプレートを参考に、自組織の運用要件に応じた情報収集・分析体制を構築してください。特に、定期的な実行スケジューリングと結果の保存・トレンド分析を組み込むことで、予防的な保守運用が可能になります。
