На сайте клиента мы используем службы Windows Server Update Services (WSUS) для развертывания обновлений продуктов на компьютерах в сети. Прежде чем служба WSUS установит обновления продуктов, необходимо вручную утвердить их для установки или включить режим автоматического утверждения, в котором нельзя выбирать устанавливаемые обновления (устанавливаются все). .
Работа ApproveUpdates.ps1 начинается с загрузки файла RequiredUpdates.txt, содержащего заголовок каждого обновления, как показано на экране. После проверки содержимого текстового файла выполняется инициализация счетчиков и файлов журналов. Сценарий записывает данные в пять журналов: found.log, expired.log, approved.log, failed.log и missing.log.
Экран. Тестовый файл RequiredUpdates.txt |
Затем сценарий ApproveUpdates.ps1 загружает сборку Microsoft.UpdateServices.Administration, которая обеспечивает использование API-интерфейса Windows.NET Framework для подключения к серверу WSUS. В частности, метод Get UpdateServer класса AdminProxy передает интерфейс (с типом данных IUpdate Server) в сервер WSUS и вносит этот интерфейс в переменную $UpdateServer.
Интерфейс IUpdateServer используется для выполнения двух важных задач, как показано в листинге. Сначала сценарий задействует метод GetComputerTargetGroups класса IUpdateServer, чтобы получить глобально уникальный идентификатор (GUID) группы компьютеров, для которого утверждаются обновления (в данном случае группа All Computers). В переменную $TargetGroup вводится ссылка на эту группу компьютеров. Затем с помощью метода GetUpdates класса IUpdateServer переменная $updates заполняется коллекцией новейших версий обновлений из базы данных WSUS, в том числе замененных и отклоненных.
Для каждого обновления продукта в этой коллекции сценарий ApproveUpdates.ps1 ищет совпадение в файле RequiredUpdates.txt. Если совпадение обнаружено, обновление записывается в журнал found.log. Затем сценарий проверяет, не истек ли срок действия обновления. Просроченные обновления заносятся в журнал expired.log, остальные отмечаются как утвержденные для установки в службе WSUS. Если эта операция выполняется успешно, сценарий добавляет обновление в журнал approved.log; если она завершается неудачей, обновление вносится в журнал failed.log.
Проверив коллекцию, ApproveUpdates.ps1 сравнивает список обнаруженных обновлений в журнале found.log со списком требуемых обновлений в файле RequiredUpdates.txt. Если обновление присутствует в файле RequiredUpdates.txt, но не в found.log, значит, обновления нет на сервере WSUS. Все отсутствующие обновления записываются в журнал missing.log.
Наконец, сценарий отображает результаты. Их также можно искать в файлах журналов.
Пользователи службы WSUS, желающие опробовать ApproveUpdates.ps1, могут ознакомиться с его кодом в листинге. Сценарий нужно запускать из каталога, в котором расположен файл RequiredUpdates.txt.
М. Самер Савас — системный администратор в компании Datel Systems and Software. Имеет сертификаты MCSE и MCTS, специализируется на работе с Active Directory, развертывании и управлении системами
# FileName: ApproveUpdates.ps1 # Created: [04/26/2010], Author: M.Samer Sawas # Requirments: -Powershell version 2.0; -Must run on local WSUS server (not remote); # -Before running this script, change to the directory where the updates text file (RequiredUpdates.txt) is located # Purpose: Approve updates for install to All Computers group, updates titles are stored in a text file # When multiple updates have the same title, the script tries to approve all of them verify updates file if (!(Test-Path -Path RequiredUpdates.txt)) {Write-Host "The updates file RequiredUpdates.txt is not located in the current directory !!!";break} # Read required updates from file into $ReqUpdatesFile and verify that it's not empty $ReqUpdatesFile = Get-Content "RequiredUpdates.txt" if ($ReqUpdatesFile -eq $null) {Write-Host "The updates file is empty !!!";break} # initialize variables and log files $UpdatesCount = 0 # all updates in WSUS database $FailedCount = 0 # updates with failed approval $ApprovedCount = 0 # updates with succeeded approval $FoundCount = 0 # matches (required updates found in WSUS database) $MissingCount = 0 # missing updates (required updates not found in WSUS database) $ExpiredCount = 0 # required updates found to be expired in WSUS database) $ApprovalSucceeded = $True Set-content Found.log $null Set-Content Missing.log $null Set-content Failed.log $null Set-content Approved.log $null Set-content Expired.log $null # Load WSUS administration [System.Reflection.Assembly]::LoadWithPartialName('Microsoft.UpdateServices.Administration') | out-null # Connect to WSUS server $updateServer = [Microsoft.UpdateServices.Administration.AdminProxy]::GetUpdateServer() # Get the computer group ID for "All Computers" group $updateServer.GetComputerTargetGroups() | foreach-object { if ($_.Name -eq "All Computers") {$TargetGroupID = $_.id;} } $TargetGroup = $updateServer.GetComputerTargetGroup($TargetGroupID) # Get updates from WSUS server $updates = $updateServer.GetUpdates() # loop through updates for approval foreach ($update in $updates) { if ($ReqUpdatesFile –contains $update.Title ) { $FoundCount = $FoundCount + 1 $updateGuid = $update.id.UpdateId # Obtain update GUID $UpdateTitleAndGUID = [string]::Concat($update.Title,"-GUID:",$updateGuid) # GUID is attached to title to uniquely identify updates add-content Found.log $UpdateTitleAndGUID # Log found updates if ($update.PublicationState -eq [Microsoft.UpdateServices.Administration.PublicationState]::Expired) { $ExpiredCount = $ExpiredCount + 1;add-content Expired.log $UpdateTitleAndGUID } else { Try{$update.Approve("Install",$TargetGroup) | out-null} Catch # executes when approval failes { $ApprovalSucceeded = $False add-content Failed.log $([string]::Concat($UpdateTitleAndGUID,", reason:",$($_.Exception.Message))) add-content Failed.log "------------------------------------" $FailedCount = $FailedCount + 1 } Finally {if ($ApprovalSucceeded) {add-content Approved.log $UpdateTitleAndGUID;$ApprovedCount = $ApprovedCount + 1} else {$ApprovalSucceeded = $True } } } } $UpdatesCount = $UpdatesCount + 1 } # Find missing updates foreach ($ReqUpdate in $ReqUpdatesFile) { if (!(select-string -path Found.log -pattern $ReqUpdate -quiet -simplematch)) {add-content Missing.log $ReqUpdate;$MissingCount = $MissingCount +1} } Function ReportUpdates($count,$state,$LogFile) { if ($Count -gt 0) { write-host $Count "update(s)" $state ":" -foregroundcolor «yellow» write-host «===============================================» Get-Content -path $LogFile | sort-object write-host } else { write-host "No updates" $state -foregroundcolor "yellow" write-host «===============================================» write-host } } ReportUpdates $MissingCount "Missing from WSUS Database" "missing.log" ReportUpdates $FoundCount "Found in WSUS Database" "Found.log" ReportUpdates $FailedCount "failed approval" "Failed.log" ReportUpdates $ExpiredCount "expired" "expired.log" ReportUpdates $ApprovedCount "Approved successfully" "Approved.log" write-host "Total number of updates processed: " $UpdatesCount -foregroundcolor "yellow"