Может ли Powershell выполнять команды параллельно?
У меня есть сценарий powershell для выполнения пакетной обработки на куче изображений, и я хотел бы сделать некоторую параллельную обработку. Powershell, похоже, имеет некоторые параметры фоновой обработки, такие как start-job, wait-job и т. д., Но единственным хорошим ресурсом, который я нашел для параллельной работы, было написание текста сценария и запуск этих ( Многопоточность PowerShell)
В идеале, я хотел бы что-то похожее на параллельный foreach в .net 4.
что-то довольно кажущийся, как:
foreach-parallel -threads 4 ($file in (Get-ChildItem $dir))
{
.. Do Work
}
может быть, мне лучше просто опуститься до c#...
5 ответов:
вы можете выполнять параллельные задания в 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
ответ Стива Таунсенда верен в теории, но не на практике, как указал @likwid. Мой пересмотренный код учитывает работа-контексте барьер--ничего не пересекает этот барьер по умолчанию! Автоматический
чтобы передать переменные из родительского контекста в дочерний контекст, используйте элемент
-ArgumentList
параметр onStart-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 в качестве подтверждающего доказательства, но, увы, мой поиск был бесплодным. Если вы случайно знаете, где задокументировано разделение контекста, напишите комментарий здесь, чтобы сообщить мне об этом!)
http://gallery.technet.microsoft.com/scriptcenter/Invoke-Async-Allows-you-to-83b0c9f0
Я создал invoke-async, который позволяет запускать несколько блоков скриптов / командлетов / функций одновременно. это отлично подходит для небольших заданий (сканирование подсети или запрос wmi против 100 машин), потому что накладные расходы на создание runspace против времени запуска 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
фоновые задания дороги для настройки и не являются многоразовыми. PowerShell MVP Oisin Grehan имеет хороший пример многопоточности PowerShell http://www.nivot.org/2009/01/22/CTP3TheRunspaceFactoryAndPowerShellAccelerators.aspx
(сайт 10/25/2010 не работает):
i'e использовал адаптированный сценарий Oisin для использования в процедуре загрузки данных здесь:
http://rsdd.codeplex.com/SourceControl/changeset/view/a6cd657ea2be#Invoke-RSDDThreaded.ps1
для завершения предыдущих ответов, вы также можете использовать
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