PowerShell: Получение информации о компьютерах в домене и TimeZone

В ночь с 29 на 30 октября 2011 в России должен был быть переход на зимнее время, однако волевым решение президента переходы на летнее и зимнее время были отменены, и Россия остается на летнем времени.  Значит многие IT специалисты столкнулись с задачей обновления всех систем и в частности, необходимо обновить все клиентские и все серверные операционные системы. Компания Microsoft выпустила очередное обновление для исправления временных зон, учитывающее последние изменения  KB2570791. Это обновление необходимо установить на все Windows машины, «для гладкого» прохождения ночи с 29 на 30 октября, без возможных последствий из-за внесенных изменений.

В случае если в текущей инфраструктуре большое количество серверов и машин, то бегать ногами к каждой машине и устанавливать обновление KB2570791 займет массу времени и сил. Поэтому, те кто привык работать головой, а не ногами (руками), давно уже имеют равернутый Microsoft Windows Server Update Services (WSUS), а то и не один.

Однако, что делать с компьютерами, которые в силы каких либо причин, находятся в домене, но не зарегистрировались на WSUS, либо из-за все возможных причин давно к нему не обращались. Один из вариантов, опросить все доступные в сети компьютеры и проверить корректность установки данного обновления. В этом нам может помочь Powershell, Vbs, AutoIT и другие подобные инструменты.

Далее предлагается один из вариантов решения задачи поиска машин в доменной сети с неустановленным обновлением KB2570791.

В качестве исходных данных, требуется только список машин в домене, его легко получить из оснастки Active Directory Users and Computers (dsa.msc), используя Saved Query. В итоге полученный список серверов и компьютеров в домене  экспортируется в csv-файл, и этот файл является источником информации о компьютерах в сети. Основная  информация, которая нам необходима в этом файле, это имя машины (поле Name).

Далее этот файл обрабатывается следующим образом:

  1. Проверяется, пингуется и ли машина
  2. Если машина пингуется, то проверяется:
    1. Текущая настройка TimeZone
    2. IP адрес
    3. Версию ОС
    4. Текущий пользователь
    5. Установлено ли обновление KB2570791
  3. На основании данных п. 2 принимается решение о статусе обновления машины.

На выходе, получим следующую информацию:

  1. Список машин, которые не пингуются
  2. Список не обновленных машин
  3. Список обновленных машин
  4. Список машин, с настройками других временных зон

Чтобы реализовать выше описанное, потребуется:

  1. функция проверки отвечает ли хост на ping
  2. функция сбора информации о хосте
  1. Чтобы проверить пингуется ли удаленная машина, используется следующий набор команд:
$ping = New-Object System.Net.NetworkInformation.Ping
$ping.Send($CompName)

Где $CompName – это имя машины

Полностью функция будет выглядеть следующим образом:

############################################################
#####   Функция проверки доступности компьютера        #####
############################################################
Function IsReply($CompName) {
    $ping = New-Object System.Net.NetworkInformation.Ping
    try
    {
        $Reply = $ping.Send($CompName)
    }
    catch
    {
        Write-host "Для машины " $CompName "не удалось выполнить ping"
    }

    return $Reply.status
}

 

  1. Чтобы собрать необходимую информацию для данной задачи о удаленной машине, понадобится несколько командлетов.
    2.1 Для получения информации о удаленной машине будет использоваться функция Get-WmiObject, и классы WMI, так как это не накладывает дополнительных требований на удаленные машины.

Командлет Get-WmiObject отображает экземпляры классов WMI или сведения о доступных классах WMI. Параметр ComputerName всегда можно использовать для указания удаленного компьютера. При задании параметра List этот командлет извлекает сведения о классах WMI, доступных в заданном пространстве имен. При указании параметра Query командлет запускает инструкцию языка запросов WMI (WQL).

Командлет Get-WmiObject не использует инфраструктуру удаленного взаимодействия Windows PowerShell для выполнения удаленных операций. Параметр ComputerName командлета Get-WmiObject можно использовать, даже если компьютер не соответствует требованиям для удаленного взаимодействия Windows PowerShell и не настроен на удаленное взаимодействие в Windows PowerShell.

Для сбора информации о машине, будут использоваться следующие WMI-классы:

  • Win32_TimeZone – для определения временной зоны
  • Win32_NetworkAdapterConfiguration – для определения настроенных IP адресов
  • Win32_OperatingSystem —  для определения версии операционной системы и Service Pack
  • Win32_ComputerSystem – для определения пользователя компьютера

Для получение полного списка доступных WMI-классов, можно использовать команду:

Get-WmiObject -List

При определении TimeZone, одно из самых наглядных параметров класса Win32_TimeZone, является свойство Caption. Его значение на обновленной машине выглядит следующим образом:

(UTC+04:00) Moscow, St. Petersburg, Volgograd

Однако как удалось заметить параметр Caption, на некоторых машинах имеет пустое значение, поэтому вместо него будет использоваться свойство BIAS. BIAS всегда имеет значение равное разнице между локальным временем и UTC.

2.2 Для получения информации о том, есть ли на удаленной машине обновление KB2570791, будет использоваться командлет Get-Hotfix.

Командлет Get-Hotfix возвращает исправления, примененные на локальном компьютере или на удаленных компьютерах с помощью компонентной модели CBS.

Но так как, получать полный список установленных обновлений, для решения данной задачи, нет необходимости, то полученные результаты отфильтруем по обновлению KB2570791:

Get-Hotfix -ComputerName $CompName | where-Object {($_.HotFixID -Like "*KB2570791*")}

Также в эту функцию будут включены операции, распределения полученной информации в соответствующие файлы. В итоге функция получения информации о компьютере будет выглядеть следующим образом:

############################################################
#####   Функция получения информации о компьютере      #####
############################################################
Function Get-Info ($CompName) {

        # Получаем информация о текущих настройках TimeZone
        $TZ = Get-WmiObject -Class "Win32_TimeZone" -namespace "root\\CIMV2" -computername $CompName -ErrorAction SilentlyContinue
        # Получаем информацию о IP адресе
        $IP = Get-WmiObject -Class "Win32_NetworkAdapterConfiguration" -namespace "root\\CIMV2" -computername $CompName -ErrorAction SilentlyContinue| Select-Object IPAddress |Where-Object { $_.IPAddress -ne $null }
        # Получаем информацию о версии операционной системы
        $OS = Get-WmiObject -Class "Win32_operatingSystem" -namespace "root\\CIMV2" -computername $CompName -ErrorAction SilentlyContinue
        #Получаем информацию о  пользователе на компьютере
        $USER = Get-WmiObject -Class "Win32_ComputerSystem" -namespace "root\\CIMV2" -computername $CompName -ErrorAction SilentlyContinue

    if ((!$TZ) -or (!$IP) -or (!$OS) -or (!$USER))
    {
        # Если ничего не удалось определить, то считаем что с компьютером не все в порядке
        return "Failed"
    }
    else
    {

        # Проверяем: установлен ли Update KB2570791
        $UpdateForTZ = Get-Hotfix -ComputerName $CompName | where-Object {($_.HotFixID -Like "*KB2570791*")}

        #Полученная информация сохраняется для поиска возможных проблем
        If ($UpdateForTZ.HotFixID -ne $null)
        {
            $IsHostFix = "There is update " + $UpdateForTZ.HotFixID
        }
        else
        {
            $IsHostFix = "There is not update KB2570791"
        }

        #Собирается вся информация в общую переменную
        $FullInfo = $CompName + ";" + $User.UserName + ";" + $IP.IPAddress + ";" + $IsHostFix + ";" + $OS.Caption + $OS.OSArchitecture + " " + $OS.CSDVersion + ";" + $OS.Version + ";" + $TZ.Bias

        #На основе собранной информации распределяются машины по разным файлам
        #1. Машина доступна, но не обновлена
        #2. Машина доступна и обновлена успешно
        #3. Настройки часового пояса отличаются от искомых (+3 или +4)

        #Проверяется параметр BIAS (Смещение от абсолютного времени)
        if ($TZ.Bias -eq 180)
        {
            $FullInfo| Out-File -Append “D:\\powershell\\Log\\NotUpdated.txt”
        }
        elseif ($TZ.Bias -eq 240)
            {
                $FullInfo| Out-File -Append “D:\\powershell\\Log\\Updated.txt”
            }
            else
            {
                $FullInfo| Out-File -Append “D:\\powershell\\Log\\Other.txt”
            }

       #Возвращаем успех
        return "Success"
    }
}

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

############################################################
#####           Начало скрипта                         #####
############################################################

#Если необходимо останавливать скрипт при возникновении ошибок в процессе выполнения
#(например при отладке), то следующую строку надо раскомментировать
#$ErrorActionPreference = "Stop"

# Обнуляем файлы, в которые записываем результаты и создаем шапку
#Файл для машин, на которых часовой пояс не изменился
("Name;User;IP_Address;Update;OS;OS_Version;Bias")| Out-File “D:\\powershell\\Log\\NotUpdated.txt”
#Файл для машин, на которых обновление прошло успешно
("Name;User;IP_Address;Update;OS;OS_Version;Bias")| Out-File “D:\\powershell\\Log\\Updated.txt”
#Файл для машин, на которых часовой пояс отличается и от старого  и от нового
("Name;User;IP_Address;Update;OS;OS_Version;Bias")| Out-File “D:\\powershell\\Log\\Other.txt”
#Файл для машин, которые в настоящий момент недоступны
("Name;User;IP_Address;Update;OS;OS_Version;Bias")| Out-File “D:\\powershell\\Log\\NotAvailable.txt”

# Загружаем исходный список машин
$List= Import-Csv "D:\\powershell\\listcomp.csv" -delimiter ';'

#Обнуляем счетчик машин
$cnt=0

# Начинаем обработку каждой машины
    foreach ( $arr in $List)
    {
        #Увеличиваем счетчик и выводим имя машины
        $cnt=$cnt+1
        Write-Host $cnt, $arr.name

        # Проверяем доступен ли компьютер
        $IsPing = IsReply($arr.name)

        #Если доступен, то собираем информацию,
        #Если не доступен, то записываем его в список недоступных машин
        if ($IsPing –eq "Success")
        {
            # Собираем информацию
            $Result = Get-Info($arr.name)

            #Если сбор информации неуспешен, то записываем его в список недоступных машин
            if ($Result –ne "Success")
            {
                $arr.name| Out-File -Append “D:\\powershell\\Log\\NotAvailable.txt”
            }
        }
        else
        {
            $arr.name| Out-File -Append “D:\\powershell\\Log\\NotAvailable.txt”
        }
    }
############################################################
#####            Конец скрипта                         #####
############################################################

После окончания работы скрипта и анализа полученных данных, файлы NotUpdated.txt и NotAvailable.txt можно обработать повторно. На основе файла NotUpdated.txt удобно проводить анализ причин отсутствия установленных обновлений.

Добавить комментарий

Этот сайт использует Akismet для борьбы со спамом. Узнайте как обрабатываются ваши данные комментариев.