2013-11-21 62 views
1

我已經做了大量的研究,但仍然無法弄清楚如何完成我想要做的事情。Powershell並行作業輸出文件

我想在100臺Linux服務器上並行執行相同的任務。

這裏是我的腳本的一個簡單的例子:

$computer=Get-Content "serverList.txt" 
[email protected]() 
$script={ 
    $cpuThresh=70 
    $cpuUsage=<Get CPU usage of the host> 
    Write-Host "CPU Usage: $cpuUsage %" 
    if ($cpuUsage -ge $cpuThresh) { 
     Write-Host "Unexpected CPU Usage" -ForegroundColor Red 
    } 
} 
foreach ($system in $computer) { 
    $jobArray += Start-Job -ScriptBlock $script -ArgumentList $system 
    While ((Get-Job -State 'Running').Count -ge 10) { 
     Start-Sleep -Milliseconds 10 
    } 
} 
foreach ($job in $jobArray) { 
    While ($job.State -eq 'Running') { 
     Start-Sleep -Milliseconds 10 
    } 
    Receive-Job -Job $job 
    Remove-Job -Job $job 
} 

我的問題是,我想寫某些消息(如意外的CPU使用率),以一個單獨的文件和多個作業試圖寫此文件在同一時間。

我的想法是將所有消息保存到數組中,並將腳本末尾的內容(第二個foreach循環)寫入文件。

但Receive-Job不返回任何變量/對象。

有沒有辦法返回變量/對象?還是有另一種方法來實現我想要做的事情?

我將不勝感激任何幫助。謝謝。

回答

0

每個職業都有至少(通常一個只有一個)子作業。該進程的輸出實際上保存在子作業的單獨輸出緩衝區中,並且可以從那裏訪問。您可以使用寫冗長的一組輸出,並寫警告另一個,並分別讀它從冗長的背部和警告流:

$computer=Get-Content "serverList.txt" 
[email protected]() 
$script={ 
    $VerbosePreference = 'Continue' 
    $Args[0] 
    $cpuThresh=70 
    $cpuUsage=<Get CPU usage of the host> 
    Write-Verbose "CPU Usage: $cpuUsage %" 
    if ($cpuUsage -ge $cpuThresh) { 
     Write-Warning "Unexpected CPU Usage" 
    } 
$Results = @{} 
$Warnings = @{} 
$Outputs = @{} 
} 
foreach ($system in $computer) { 
    $jobArray += Start-Job -ScriptBlock $script -ArgumentList $system 
    While ((Get-Job -State 'Running').Count -ge 10) { 
     Start-Sleep -Milliseconds 10 
    } 
} 
foreach ($job in $jobArray) { 
    While ($job.State -eq 'Running') { 
     Start-Sleep -Milliseconds 10 
    } 
    $Server = $Job.ChildJobs[0].Output[0] 
    $Results[$Server] = $Job.ChildJobs[0].Verbose 
    $Warnings[$Server] = $Job.ChildJobs[0].Warning 
    $Outputs[$Server] = $Job.ChildJobs[0].Output 

    Remove-Job -Job $job 
} 

編輯:更新的所有本地就業機會。

+0

非常感謝您的快速回復。應該考慮使用不同的輸出流... 我唯一的問題是$ job.ChildJobs [0] .Warning返回一個包含所有消息的對象。 什麼是擺脫消息頭的最佳方式? 寫輸出$警告|選擇消息| Format-Table -HideTableHeaders 這就是我現在正在做的。有更好的解決方案嗎? – user3015914

+0

$警告|寫輸出似乎工作 – mjolinor

2

Receive-Job沒有得到任何結果,因爲使用Write-Host即 不是標準輸出。將行Write-Host "Unexpected CPU Usage" -ForegroundColor Red替換爲"Unexpected CPU Usage"Receive-Job應該 開始接收消息。在處理Receive-Job時,在腳本的最後部分使用Write-Host -ForegroundColor Red

此外,我會建議看看模塊 SplitPipeline這是 專門爲這些任務而設計的。您的腳本可以使用命令 Split-Pipeline及其代碼將被減少到最低限度:

Get-Content "serverList.txt" | Split-Pipeline -Count 10 {process{ 
    $cpuThresh=70 
    $cpuUsage = ... # Get CPU usage of the host, use $_ as the current input server 
    "CPU Usage: $cpuUsage %" # standard output 
    if ($cpuUsage -ge $cpuThresh) { 
     "Unexpected CPU Usage" # "warning" to be analysed later 
     # or even better, Split-Pipeline takes care of warnings: 
     Write-Warning "Unexpected CPU Usage" 
    } 
}} | % { 
    # process output here, e.g. normal messages goes to a log file 
    # and warnings are processed as 
    Write-Host "Unexpected CPU Usage" -ForegroundColor Red 

    # or if you used Write-Warning above this is not even needed 
} 
+0

感謝您的回覆。 我一定會看看SlitPipeline,但現在使用不同的輸出流對我來說是更好的解決方案。 – user3015914

+0

是的,看看。 'Split-Pipeline'負責並行處理的所有日常工作。與此同時,它的輸出被同步處理,就好像不使用並行處理一樣。 –

相關問題