2012-06-16 2 views
1

Я пытаюсь использовать задания для одновременного запуска PowerShell, чтобы мой скрипт мог закончить быстрее. Сценарии, которые я вызываю, являются независимыми, не требуют взаимного исключения и т. Д. Проблема в том, что он будет вызывать пять из 50 сценариев, а затем он остановится. Остальные сценарии никогда не работают. Что-то не так с ожиданием? Кроме того, по какой-то причине пять сценариев, которые фактически управляют, кажется, будет выполняться два раза, так что я получить двойной выход ...Не все мои задания PowerShell v2 запускаются

$Invocation = (Get-Variable MyInvocation -Scope 1).Value 
$ScriptDir = Split-Path $Invocation.MyCommand 
$ScriptDir -match '(?<content>.*\d)' | out-null 
$MainDir = $matches['content'] 
$ScriptName = $MyInvocation.MyCommand.Name 
$Items = Get-ChildItem -Path $MainDir | Where-Object {$_.mode -match "d"} 

$jobMax = 4 
$jobs = @() 

$jobWork = { 
    param ($MyInput,$dir) 
    $command = "$dir\" + $MyInput.name + "\" + $MyInput.name + ".ps1" 
    Start-Process powershell.exe -argumentlist $command -WindowStyle Hidden #-wait 
} 

foreach ($Item in $Items) { 
    if ($jobs.Count -le $jobMax) { 
     $jobs += Start-Job -ScriptBlock $jobWork -ArgumentList $Item,$MainDir 
    } else { 
     $jobs | Wait-Job -Any 
    } 
} 
$jobs | Wait-Job 

Edit: Кроме того, поскольку я использую запуска процесса PowerShell все сценарии запуска одновременно (если Я включаю -wait), без необходимости запуска. Я хотел использовать задания, чтобы я мог дросселировать. Может быть, это неправильная логика, что у меня есть работа, начинающая новый экземпляр powershell?

Edit2: Как я думал, было неправильно использовать start-job для запуска нового экземпляра poweshell. Таким образом, работа была выполнена после того, как она открыла новый экземпляр powershell, фактическое содержимое скрипта не имело ничего общего с началом и завершением задания. Вот мой фиксированный сценарий :)

$Invocation = (Get-Variable MyInvocation -Scope 1).Value 
$ScriptDir = Split-Path $Invocation.MyCommand 
$ScriptDir -match '(?<content>.*\d)' | out-null 
$MainDir = $matches['content'] 
$ScriptName = $MyInvocation.MyCommand.Name 
$Items = Get-ChildItem -Path $MainDir | Where-Object {$_.mode -match "d"} 

$maxJobs = 4 
$jobs = @() 

foreach ($Item in $Items) { 
    $command = "$MainDir\" + $Item.name + "\" + $Item.name + ".ps1" 
    $jobs += Start-Job -filepath $command -ArgumentList $MainDir,$Item 
    $running = @($jobs | ? {$_.State -eq 'Running'}) 

    while ($running.Count -ge $maxJobs) { 
     $finished = Wait-Job -Job $jobs -Any 
     $running = @($jobs | ? {$_.State -eq 'Running'}) 
    }  
} 
Wait-Job -Job $jobs > $null 

Я должен был изменить весь мой сценарий так, чтобы я мог передать аргументы в качестве параметров, но теперь все работает отлично. Эта тема была полезна Running multiple scriptblocks at the same time with Start-Job (instead of looping)

ответ

0

Моя догадка (после просмотра вашего кода) заключается в том, что вы получите только первые 4 задания. Работа (даже завершена) не исчезает автоматически. Вам нужно очистить их, как только они будут завершены (возможно, сначала получить работу). Если вы этого не сделаете - PowerShell вернет задания $ jobsMax, и как только это будет сделано - я был бы очень удивлен, увидев других «новичков».

Добавить логику получения/удаления задания, и она должна работать лучше.

Также: насколько я могу судить, вы используете скрипты, поэтому я бы предложил использовать параметр -File для powershell.exe, а не -команды.

НТН Bartek

+0

Спасибо за ответ. См. Мое редактирование. Получение/удаление задания не было проблемой. Но ваш последний комментарий о параметре -file был немного ближе и помог мне пойти в правильном направлении об исправлении этого. Благодарю. – kokotas