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
}

 

2. Чтобы собрать необходимую информацию для данной задачи о удаленной машине, понадобится несколько командлетов.
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 удобно проводить анализ причин отсутствия установленных обновлений.

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