ウェブサイト検索

PowerShellを使用して無料でWindows Serverのインベントリレポートを作成する方法


PowerShellは多くのサーバー管理者によって使用されています。自然に、最もよく使われる作業の一つは、サーバーをインベントリし、環境に何があるかを理解するためのスクリプトと関数を構築する能力です。

このことを達成する方法はいくつかありますが、複雑さの度合いは様々です。本記事では、かなりシンプルですが効果的なWindows Serverインベントリレポートを作成します。

前提条件

この記事は実践的な内容になります。一緒に進める予定の方は、まず以下の前提条件が整っていることを確認してください。

  • Active Directory (AD) ドメインに参加している Windows 10 PC で作業中です。
  • RSATツールキットからActiveDirectory PowerShellモジュールをインストールしてください。
  • ADコンピューターアカウントにクエリを実行する許可を得る
  • リモートコンピュータに対してリモートWMI/CIMクエリを実行できます
  • リモートコンピューターでPowerShellリモーティングを利用可能にする

サーバーを取得しています

私たちが構築しているスクリプトの基盤となるのは、サーバー自体です。サーバーを個別にテキストファイルに書き出して読み込むことも、スクリプト内の配列にして書くこともできますが、PowerShellを使用すると、さらに良い方法があります。スクリプトをより動的にし、新しいサーバーが追加されるたびに修正を必要としないようにするために、Active Directory (AD) を使用して特定の組織単位 (OU) 内のコンピュータオブジェクトのリストを取得できます。

以下では、私たちは利用しています

ActiveDirectory

RSATツールキットに利用可能なモジュール、クエリを実行するための

Servers

OUにあり、そこからすべてのコンピュータオブジェクトを取得します。

Get-ADComputer
Import-Module ActiveDirectory
$OU = 'OU=Servers,DC=domain,DC=local'
$Params = @{
    "SearchBase" = $OU
    "Filter" = '*'
}
$Servers = Get-ADComputer @Params

この時点で、$servers変数を埋めるために名前プロパティだけをフィルタリングすることもできましたが、しばしば後で利用するために返された全体のオブジェクトを持っていることが非常に便利です。

収集するデータの決定

サーバーが揃ったので、各サーバーから何を正確に収集すべきかを考える必要があります。フルADオブジェクトを保持することが重要である理由の一つは、そのデータをサーバー自体からのデータと組み合わせて、環境の全体像を把握するためです。

実際に、こういったことはどのようなものに見えるのでしょうか?知っておくと非常に役立ついくつかの特性を挙げてみましょう。

サーバー値

  • サーバーホスト名
  • 空きディスクスペース
  • 記憶
  • ネットワーク接続

ADの価値

  • パスワード最後の設定日
  • 最終ログオン
  • DNSホスト名

サーバー情報の取得

返却されたサーバーのリストからこの情報を収集するにはどうすればよいでしょうか?サーバーのリストがあるので、$Serversオブジェクトを繰り返し処理してクエリを実行する必要があります。以下の簡単なForeach-Objectループから始めて、値を保持するカスタムオブジェクトを作成できます。

$Servers | Foreach-Object {
    [PSCustomObject]@{
        "ServerHostName" = $_.Name
        "Description" = $_.Description
        "FreeDiskSpace" = $Null
        "TotalMemory" = $Null
        "NetworkConnections" = $Null
        "PasswordLastSet" = $_.pwdLastSet
        "LastLogon" = $_.lastLogon
        "DNSHostName" = $_.DNSHostName
        "CreationDate" = $_.WhenCreated
    }
}

ご覧のように、最初にコンピュータを取得した際にActive Directoryから完全なオブジェクトを保存することで、幅広い情報を取得することができます。しかし、残念ながら、これは私たちが必要とする情報のすべてではありません。

各サーバーから情報を取得するために、多くのサーバー管理者に馴染みのあるインターフェースであるWindows管理インストゥルメンテーション(WMI)インターフェースを利用します。以下で使用されるコマンドレットが、WMIがこの標準のMicrosoftの実装である共通情報モデル(CIM)インターフェースのものであることに気付くかもしれません。

無料のディスクスペースを取得する

Win32_LogicalDiskの利用可能なWMIクラスを使用することで、利用可能なすべてのディスクとその空き容量を取得できます。コマンドGet-CimInstance -ClassName Win32_LogicalDiskを最初に実行すると、デフォルトの出力では必ずしも読みやすくないことに気付くかもしれません。

ここでの二つ目の問題は、返されるドライブが複数あることです。それぞれのドライブについて、使用可能な空き容量が何GBあるのか知りたいです。コードを修正して、一部の変換を行い、より良くしましょう。

$Disks = Get-CimInstance -ClassName Win32_LogicalDisk
$DisksResult = $Disks | Foreach-Object {
    [PSCustomObject]@{
        "Drive" = $_.DeviceID
        "FreeSpace" = [Math]::Round(($_.FreeSpace / 1GB),2)
    }
}
$DisksResult

コマンドを実行した後、出力ははるかにクリーンになり、スクリプトで使用できるようになりました。

しかし、もし低ディスクスペースの状況を警告したい場合はどうでしょうか?その条件を満たす各ドライブにフラグを設定するために、これをわずかに拡張するのが良いでしょう。空き容量を総利用可能容量と比較することで、それが10%または10GB未満であるかどうかを確認できます。-or条件の理由は、非常に大きなディスクの場合、10%がまだ非常に寛大である可能性があるため、絶対的な制限を設けることが助けになるからです。

$Disks = Get-CimInstance -ClassName Win32_LogicalDisk
$DisksResult = $Disks | Foreach-Object {
  $FreeSpace = [Math]::Round(($_.FreeSpace / 1GB),2)
  $TotalSpace = [Math]::Round(($_.Size / 1GB),2)
  If ( ($FreeSpace / $TotalSpace -LT 0.10) -Or $FreeSpace -LT 10 ) {
    $LowDiskSpace = $True
  } Else {
    $LowDiskSpace = $False
  }
    [PSCustomObject]@{
        "Drive" = $_.DeviceID
    "FreeSpace" = $FreeSpace
    "LowDiskSpace" = $LowDiskSpace
    }
}
$DisksResult

ご覧のとおり、私たちのサーバーに保存すべき素晴らしい情報が揃っています。

使用可能なメモリを取得する

各サーバーに割り当てられているRAMの量を把握しておくことは便利です。特に仮想マシン環境では重要です。過剰に提供されているサーバーがある場合、サーバーの適正化によって貴重なリソースを節約できます。幸いなことに、これは取得するのがはるかに簡単です。

Win32_PhysicalMemory WMI クラスを使用して、返されたすべての Capacity プロパティを合計することで、総メモリを取得できます。

(Get-CimInstance -ClassName Win32_PhysicalMemory | Measure-Object -Property Capacity -Sum).Sum / 1GB

すべてのネットワーク接続を取得する

最後に、すべてのネットワーク接続を一緒に取得したいと思います。これは、特定のサーバーに複数のインターフェースがあるかどうかを知るのに役立ちます。今回は少し異なるメカニズムを使用しており、Get-NetAdapter コマンドレットを使用していますが、これには ComputerName パラメータがないため、PSリモーティングを使用してターゲットサーバー上でローカルに呼び出し、その結果をスクリプトに返します。

$NetworkConnections = Invoke-Command -ComputerName $_.DnsHostName -ScriptBlock {
    Get-NetAdapter -Physical | Select-Object Name, Status, LinkSpeed
}

私たちの出力は以下のようになります。そして、これを私たちのスクリプトに保存することができます。

Invoke-Commandが機能するためには、ターゲットサーバーにPSリモーティングが設定されている必要があることを心に留めておいてください。

全てをまとめる

すべての部品が揃ったので、これをまとめましょう。最終的なスクリプトは以下にあり、報告したい内容をまとめたカスタム出力オブジェクトを作成するためのすべてのコードが組み合わされています。

Import-Module ActiveDirectory
$OU = 'OU=Servers,DC=domain,DC=local'
$Params = @{
    "SearchBase" = $OU
    "Filter" = '*'
}
$Servers = Get-ADComputer @Params
$Servers | Foreach-Object {
  $Disks = Get-CimInstance -ComputerName $_.DnsHostName -ClassName Win32_LogicalDisk
  $DisksResult = $Disks | Foreach-Object {
    [PSCustomObject]@{
      "Drive" = $_.DeviceID
      "FreeSpace" = [Math]::Round(($_.FreeSpace / 1GB),2)
    }
  }
  
  $NetworkConnections = Invoke-Command -ComputerName $_.DnsHostName -ScriptBlock {
    Get-NetAdapter -Physical | Select-Object Name, Status, LinkSpeed
  }
    [PSCustomObject]@{
        "ServerHostName" = $_.Name
        "Description" = $_.Description
        "FreeDiskSpace" = $DisksResult
        "TotalMemory" = ((Get-CimInstance -ComputerName $_.DnsHostName -ClassName Win32_PhysicalMemory | Measure-Object -Property Capacity -Sum).Sum / 1GB)
        "NetworkConnections" = $NetworkConnections
        "PasswordLastSet" = $_.pwdLastSet
        "LastLogon" = $_.lastLogon
        "DNSHostName" = $_.DNSHostName
        "CreationDate" = $_.WhenCreated
    }
}

結論

ここで示したものは、在庫報告書のために作成できるものの氷山の一角に過ぎません。この報告書に追加できるさらに多くの便利なプロパティがあります。それをさらに進めると、これをHTMLページに組み込んだり、毎週実行するタスクをスケジュールしたり、Ansibleなどの他のツールに組み込むこともできます。

PowerShellは、必要な情報を簡単に一箇所にまとめることができます。環境を分析し、知るべきことを決定したら、PowerShellでレポートを作成し、将来的に環境を監査する能力を強化してください。

関連記事: