【WIndows】Windowsサーバーからsysteminfoコマンドで取得した情報を効率的にパース・集約・分析する

業務効率化

今回は、複数の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の出力を取得・フォーマット化

基本的なパース方法

「パース(Parse)」とは

パースとは、テキストなどの非構造化データを、プログラムが扱いやすい構造化データに分解・解析する処理のことです。
たとえば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出力などの機能を活用すれば、運用業務の自動化・効率化が実現できます。

本記事で解説したスクリプトテンプレートを参考に、自組織の運用要件に応じた情報収集・分析体制を構築してください。特に、定期的な実行スケジューリング結果の保存・トレンド分析を組み込むことで、予防的な保守運用が可能になります。

 

【注意】

このブログは技術に関する知識や経験を共有することを目的としており、情報の正確性に努めていますが、その内容の正確性や完全性を保証するものではありません。ブログの情報を利用する場合は、自己の責任において行動してください。ブログの内容に基づいて行った行動や決定によって生じた損害や被害について、筆者は一切の責任を負いません。

 

記事の内容の一部は、生成AIで作成しています。

業務効率化windowsITナレッジ
この記事の作者
StarTeller

30歳で異業種からITエンジニアへ転身し、10年以上にわたりインフラエンジニアとして様々な現場でシステム構築・運用に携わってきました。
得意分野はLinux/Windowsのサーバー構築・運用で、ネットワークやAWSなども実務で活用しています。このブログでは、これまでの業務で培った経験を基に、日々の業務で遭遇した問題の解決方法や、システム構築の具体的な手順を解説。現場のエンジニアが実際に「困ったとき」に参照できる情報を意識して投稿していこうと思っています。
※サーバ運用費がかかっているので、広告を掲載させて頂いてます。

StarTellerをフォローする
シェアする
StarTellerをフォローする
タイトルとURLをコピーしました