start-job Выполняет команду параллельно и выводит результат по мере их поступления

Я пытаюсь получить конкретное существование KBXXXXXX в списке серверов, но после того, как мой скрипт на одном сервере требует времени и возвращает результат, возвращается, а затем переходит к следующему. этот сценарий отлично работает для меня. Я хочу, чтобы мой скрипт запускался и запускал исправление как задание и другой процесс, просто чтобы собрать результаты и отобразить их.

$servers = gc .\list.txt 
foreach ($server in $servers) 
{ 
    $isPatched = (Get-HotFix -ComputerName $server | where HotFixID -eq 'KBxxxxxxx') -ne $null 
    If ($isPatched) 
    { 
    write-host $server + "Exist">> .\patchlist.txt} 
    Else  
    { 
    Write-host $server +"Missing"
$server  >> C:\output.txt
    } 

}

Цель состоит в том, чтобы список выполнялся быстрее, а не запускался последовательно.


person Fenomatik    schedule 27.03.2013    source источник
comment
Взгляните на аналогичный вопрос stackoverflow.com/questions/15580105/   -  person Roman Kuzmin    schedule 28.03.2013


Ответы (3)


С Powershell V2 вы можете использовать задания, как в ответе @Andy, или более подробно по этой ссылке Может ли Powershell запускать команды параллельно?

В PowerShell V2 вы также можете проверить этот скрипт http://gallery.technet.microsoft.com/scriptcenter/Foreach-Parallel-Parallel-a8f3d22b с использованием пространств выполнения

В PowerShell V3 у вас есть опция foreach -parallel.

например (NB Measure-Command используется только для расчета времени, чтобы вы могли сравнить)

Workflow Test-My-WF {  
  param([string[]]$servers)

  foreach -parallel ($server in $servers) {

    $isPatched = (Get-HotFix -ComputerName $server | where {$_.HotFixID -eq 'KB9s82018'}) -ne $null     
    If ($isPatched) 
    { 
        $server | Out-File -FilePath "c:\temp\_patchlist.txt" -Append
    } 
    Else  
    { 
        $server | Out-File -FilePath "c:\temp\_output.txt" -Append 
    } 
  }
}

Measure-Command -Expression { Test-My-WF   $servers }
person Paul Rowland    schedule 28.03.2013

Для этого используйте задания PowerShell.

командлеты:

  • Найти работу
  • Получение работы
  • Удалить работу
  • Старт-Работа
  • Стоп-Работа
  • Подождите-Job

Вот непроверенный пример:

$check_hotfix = {
    param ($server)
    $is_patched = (Get-HotFix -ID 'KBxxxxxxx' -ComputerName $server) -ne $null 
    if ($is_patched) { 
        Write-Output ($server + " Exist") 
    } else { 
        Write-Output ($server + " Missing")
    }
}

foreach ($server in $servers) {
    Start-Job -ScriptBlock $check_hotfix -ArgumentList $server | Out-Null
}

Get-Job | Wait-Job | Receive-Job | Set-Content patchlist.txt
person Andy Arismendi    schedule 28.03.2013

Вместо использования заданий используйте возможность запрашивать несколько компьютеров, встроенных в командлет. Многие командлеты Microsoft, особенно те, которые используются для управления системой, принимают массив строк в качестве входных данных для параметра -Computername. Передайте свой список серверов, и командлет запросит их все. Большинство командлетов, обладающих этой возможностью, будут запрашивать серверы последовательно, но Invoke-Command будет делать это параллельно.

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

$servers = gc .\list.txt 
$patchedServers = Get-HotFix -ComputerName $servers | where HotFixID -eq 'KBxxxxxxx'|select machinename

$unpatchedServers = compare-object -referenceobject $patchedServers -differenceobject $servers -PassThru

$unpatchedServers |out-file c:\missing.txt;
$patchedServers|out-file c:\patched.txt;

В параллели:

$servers = gc .\list.txt 
$patchedServers = invoke-command -computername $servers -scriptblock {Get-HotFix | where HotFixID -eq 'KBxxxxxxx'}|select -expandproperty pscomputername |sort -unique

Как и раньше, у меня нет подходящей версии Windows, доступной на данный момент, чтобы протестировать вышеуказанное и проверить результат, но это отправная точка.

person alroc    schedule 28.03.2013
comment
@alroc, это интересно, не могли бы вы дать ссылку на некоторые онлайн-статьи о таком типе параллельной обработки. Спасибо - person Paul Rowland; 28.03.2013
comment
@PaulRowland, к сожалению, мне трудно найти хорошую документацию о том, как это работает. См. Справку по Get-Hotfix и первые несколько обращений здесь. Работа хороша, когда она вам нужна, но она может внести ненужную сложность. Используйте то, что вам предоставляет PowerShell - MS, вероятно, выполнила параллелизм лучше, чем вы. - person alroc; 28.03.2013
comment
@alroc - спасибо, но я не видел, где это предлагает делать их параллельно. Было бы также интересно узнать, скрыто ли это то же самое, что и использование опции foreach -parallel. У меня сейчас нет под рукой тестовых серверов, но я могу запустить сценарий, чтобы сравнить их. - person Paul Rowland; 28.03.2013
comment
Приведенный выше код не помог ускорить процесс, выполнив серию одинаковых команд на разных серверах параллельно. - person Fenomatik; 28.03.2013
comment
Меня поправили через Twitter; invoke-command выполняется параллельно, но другие командлеты работают последовательно (см. Раздел «Получение информации WMI с нескольких компьютеров» здесь). Вы можете использовать описанную там технику, чтобы использовать Invoke-Command для получения параллелизма, не прибегая к заданиям. - person alroc; 28.03.2013