Поиск по сайту:

Как бесплатно создать отчет об инвентаризации Windows Server с помощью PowerShell


PowerShell используется многими администраторами серверов. Естественно, одной из наиболее часто используемых задач является возможность создания сценариев и функций для инвентаризации ваших серверов и понимания того, что есть в вашей среде.

Хотя есть много способов сделать это с разным уровнем сложности, в этой статье мы собираемся создать довольно простой, но эффектный отчет об инвентаризации Windows Server.

Предпосылки

Эта статья будет практической. Если вы собираетесь продолжить, сначала убедитесь, что у вас выполнены следующие предварительные условия:

  • Работа на ПК с Windows 10, присоединенном к домену Active Directory (AD)
  • Установите модуль ActiveDirectory PowerShell из набора инструментов RSAT.
  • Иметь разрешение запрашивать учетные записи компьютеров AD
  • Может запускать удаленные запросы WMI/CIM к удаленным компьютерам
  • Доступность удаленного взаимодействия PowerShell на удаленных компьютерах

Получение серверов

Основой сценария, который мы создаем, являются сами серверы. Вы можете записать их по отдельности в текстовый файл, который считывается, или в массив внутри самого скрипта, но с помощью PowerShell мы можем сделать это лучше. Чтобы сделать сценарий более динамичным и не требовать от нас его изменения каждый раз при добавлении нового сервера, мы можем использовать Active Directory (AD) для извлечения списка объектов-компьютеров в данной организационной единице (OU).

Ниже мы используем модуль ActiveDirectory, доступный в наборе инструментов RSAT, для запроса организационной единицы Servers и извлечения всех объектов-компьютеров с помощью Get-ADComputer..

Import-Module ActiveDirectory

$OU = 'OU=Servers,DC=domain,DC=local'

$Params = @{
    "SearchBase" = $OU
    "Filter"     = '*'
}

$Servers = Get-ADComputer @Params

На этом этапе мы могли бы отфильтровать только свойство name, чтобы заполнить переменную $servers, но часто очень полезно иметь весь возвращаемый объект для последующего использования.

Определение данных для сбора

Теперь, когда у нас есть наши серверы, нам нужно выяснить, что именно мы должны собирать с каждого сервера. Одной из причин, по которой может быть важно сохранить полный объект 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). Вы можете заметить, что используемые ниже командлеты взяты из интерфейса Common Information Model (CIM), WMI которого является реализацией Microsoft этого стандарта.

Получить свободное место на диске

Используя доступный класс WMI Win32_LogicalDisk, мы можем получить все доступные диски и их свободное пространство. Когда мы впервые запускаем команду Get-CimInstance -ClassName Win32_LogicalDisk, вы можете заметить, что ее выходные данные по умолчанию не совсем читаемы.

Вторая проблема заключается в том, что у нас возвращается более одного диска. Я хотел бы знать о каждом из этих дисков и о том, сколько свободного места доступно в ГБ. Давайте изменим код, чтобы сделать некоторые преобразования и сделать его лучше.

$Disks = Get-CimInstance -ClassName Win32_LogicalDisk

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

$DisksResult

После того, как мы запустили команды, наш вывод стал намного чище, и теперь его можно использовать в нашем скрипте.

Но что, если мы хотим предупредить о нехватке места на диске? Было бы неплохо немного расширить это, чтобы установить флаг для каждого диска, который соответствует этому условию. Сравнивая свободное пространство с общим доступным пространством, мы можем увидеть, меньше ли оно 10% или 10 ГБ. Причина использования условия -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

Как вы уже поняли, у нас есть большой набор информации, которую нужно хранить на наших серверах.

Получите доступную память

Удобно знать, сколько оперативной памяти выделено каждому серверу, особенно в среде виртуальной машины. Если вы обнаружите, что некоторые серверы выделены с избытком, вы можете сэкономить ценные ресурсы, изменив размер серверов. К счастью, это гораздо проще получить.

Используя класс WMI Win32_PhysicalMemory, мы можем просуммировать все возвращенные свойства Capacity, чтобы получить общий объем памяти.

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

Получить все сетевые подключения

Наконец, мы хотим получить все сетевые соединения вместе. Это полезно знать, если у определенного сервера есть несколько интерфейсов, о которых нужно беспокоиться. На этот раз мы используем немного другой механизм, мы используем командлет Get-NetAdapter, но поскольку у него нет параметра ComputerName, мы будем использовать PS Remoting для вызова это локально на целевом сервере и вернуть результаты нашему сценарию.

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

Наш вывод будет похож на приведенный ниже, и мы можем затем сохранить его в наш скрипт.

Имейте в виду, что для работы Invoke-Command необходимо настроить PS Remoting на целевых серверах.

Собираем все вместе

Теперь, когда у нас есть все части, давайте соберем все вместе. Окончательный сценарий приведен ниже и объединяет весь код для создания пользовательского объекта вывода только с тем, о чем мы хотим сообщить.

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, чтобы подтвердить свою способность проводить аудит своей среды в будущем.