Может ли Powershell запускать команды параллельно? - PullRequest
108 голосов
/ 25 октября 2010

У меня есть сценарий powershell для выполнения пакетной обработки нескольких изображений, и я бы хотел выполнить параллельную обработку.Похоже, в Powershell есть некоторые параметры фоновой обработки, такие как запуск, ожидание и т. Д., Но единственный хороший ресурс, который я нашел для параллельной работы, - это написание текста сценария и его запуск ( PowerShell Multithreading )

В идеале, я бы хотел что-то похожее на параллельный foreach в .net 4.

Что-то вроде этого:

foreach-parallel -threads 4 ($file in (Get-ChildItem $dir))
{
   .. Do Work
}

Может быть, я был бы лучшевыкл просто опускаясь до c # ...

Ответы [ 6 ]

89 голосов
/ 21 июля 2011

Ответ от Стива Таунсенда верен в теории, но не на практике, как указал @likwid. Мой пересмотренный код учитывает барьер контекста задания - по умолчанию ничто не пересекает этот барьер! Таким образом, автоматическая переменная $_ может использоваться в цикле, но не может использоваться непосредственно в блоке сценария, поскольку она находится в отдельном контексте, созданном заданием.

Чтобы передать переменные из родительского контекста в дочерний контекст, используйте параметр -ArgumentList в Start-Job, чтобы отправить его, и используйте param внутри блока скрипта, чтобы получить его.

cls
# Send in two root directory names, one that exists and one that does not.
# Should then get a "True" and a "False" result out the end.
"temp", "foo" | %{

  $ScriptBlock = {
    # accept the loop variable across the job-context barrier
    param($name) 
    # Show the loop variable has made it through!
    Write-Host "[processing '$name' inside the job]"
    # Execute a command
    Test-Path "\$name"
    # Just wait for a bit...
    Start-Sleep 5
  }

  # Show the loop variable here is correct
  Write-Host "processing $_..."

  # pass the loop variable across the job-context barrier
  Start-Job $ScriptBlock -ArgumentList $_
}

# Wait for all to complete
While (Get-Job -State "Running") { Start-Sleep 2 }

# Display output from all jobs
Get-Job | Receive-Job

# Cleanup
Remove-Job *

(Я обычно хотел бы предоставить ссылку на документацию PowerShell в качестве подтверждающего доказательства, но, увы, мой поиск оказался бесплодным. Если вам случится узнать, где задокументировано разделение контекста, оставьте здесь комментарий, чтобы сообщить мне!) 1014 *

84 голосов
/ 25 октября 2010

Вы можете выполнять параллельные задания в Powershell 2, используя Фоновые задания . Ознакомьтесь с Start-Job и другими командлетами заданий.

# Loop through the server list
Get-Content "ServerList.txt" | %{

  # Define what each job does
  $ScriptBlock = {
    param($pipelinePassIn) 
    Test-Path "\\$pipelinePassIn\c`$\Something"
    Start-Sleep 60
  }

  # Execute the jobs in parallel
  Start-Job $ScriptBlock -ArgumentList $_
}

Get-Job

# Wait for it all to complete
While (Get-Job -State "Running")
{
  Start-Sleep 10
}

# Getting the information back from the jobs
Get-Job | Receive-Job
8 голосов
/ 01 марта 2013

http://gallery.technet.microsoft.com/scriptcenter/Invoke-Async-Allows-you-to-83b0c9f0

я создал invoke-async, который позволяет вам одновременно запускать несколько блоков / командлетов / функций скрипта.это отлично подходит для небольших заданий (сканирование подсети или запрос wmi к сотням машин), поскольку накладные расходы на создание пространства выполнения и время запуска start-job довольно значительны.Может использоваться следующим образом.

со скриптовым блоком,

$sb = [scriptblock] {param($system) gwmi win32_operatingsystem -ComputerName $system | select csname,caption} 

$servers = Get-Content servers.txt 

$rtn = Invoke-Async -Set $server -SetParam system  -ScriptBlock $sb

просто командлет / функция

$servers = Get-Content servers.txt 

$rtn = Invoke-Async -Set $servers -SetParam computername -Params @{count=1} -Cmdlet Test-Connection -ThreadCount 50
7 голосов
/ 25 октября 2010

Фоновые задания дороги в настройке и не подлежат повторному использованию. PowerShell MVP Ойсин Грехан имеет хороший пример многопоточности PowerShell http://www.nivot.org/2009/01/22/CTP3TheRunspaceFactoryAndPowerShellAccelerators.aspx

(25.10.2010 сайт закрыт):

Я использовал адаптированный скрипт Oisin для использования в подпрограмме загрузки данных здесь:

http://rsdd.codeplex.com/SourceControl/changeset/view/a6cd657ea2be#Invoke-RSDDThreaded.ps1

3 голосов
/ 02 октября 2018

Чтобы завершить предыдущие ответы, вы также можете использовать Wait-Job, чтобы дождаться завершения всех заданий:

For ($i=1; $i -le 3; $i++) {
    $ScriptBlock = {
        Param (
            [string] [Parameter(Mandatory=$true)] $increment
        )

        Write-Host $increment
    }

    Start-Job $ScriptBlock -ArgumentList $i
}

Get-Job | Wait-Job | Receive-Job
0 голосов
/ 10 июля 2019

В эти дни есть так много ответов:

  1. заданий (или потоковых заданий в PS 6 или модуле)
  2. start-process
  3. рабочих процессов
  4. PowerShell API с другим пространством выполнения
  5. invoke-команда с несколькими компьютерами, которые все могут быть localhost

Вот foreach -parallel:

workflow work {
  foreach -parallel ($i in 1..3) { 
    sleep 5 
    "$i done" 
  }
}

work

3 done
1 done
2 done
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...