1

スクリプトをより速く終了できるように、ジョブを使用してPowerShellのインスタンスを同時に実行しようとしています。私が呼び出しているスクリプトはすべて独立しており、相互排除などの必要はありません。問題は、50個のスクリプトのうち5個を呼び出してから、停止することです。残りのスクリプトは実行されていないようです。待機ジョブに何か問題がありますか?また、何らかの理由で、実際に実行される5つのスクリプトが2回実行されているように見えるため、2つの出力が得られます...

$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

編集:また、start-process powershellを使用しているため、start-jobを必要とせずに、すべてのスクリプトが同時に実行されます(-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

引数をパラメーターとして渡すことができるように、すべてのスクリプトを編集する必要がありましたが、今ではすべてが正常に機能します。このスレッドは、(ループする代わりに)Start-Jobで同時に複数のスクリプトブロックを実行するのに役立ちました

4

1 に答える 1

0

私の推測では (あなたのコードを見て)、最初の 4 つのジョブしか開始されないということです。ジョブ (完了したものであっても) が自動的に消えることはありません。それらが完了したら、それらをきれいにする必要があります (おそらく Receive-Job の最初のもの)。そうしないと、PowerShell は $jobsMax ジョブをスピンし、それが完了すると、他の「新規参入者」が現れることに本当に驚かれることでしょう。

Receive/Remove ジョブ ロジックを追加すると、より適切に機能するはずです。

また、スクリプトを実行していることがわかる限り、-command ではなく、powershell.exe で -File パラメータを使用することをお勧めします。

HTH バーテック

于 2012-06-16T16:11:50.900 に答える