Powershell并行作业输出文件

时间:2013-11-21 04:31:21

标签: powershell parallel-processing start-job

我已经做了很多研究,但仍然无法弄清楚如何完成我想做的事。

我想在100台Linux服务器上并行执行相同的任务。

以下是我的脚本的简化示例:

$computer=Get-Content "serverList.txt"
$jobArray=@()
$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不会返回任何变量/对象。

有没有办法返回变量/对象?还是有另一种方法来实现我想做的事情吗?

我将不胜感激任何帮助。感谢。

2 个答案:

答案 0 :(得分:2)

Receive-Job没有得到任何结果,因为Write-Host被使用了 不是标准输出。将行Write-Host "Unexpected CPU Usage" -ForegroundColor Red替换为"Unexpected CPU Usage"Receive-Job应该 开始接收消息。在{中使用Write-Host -ForegroundColor Red 处理Receive-Job时脚本结束。

另外,我建议您查看该模块 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
}

答案 1 :(得分:0)

每份工作至少(通常只有一份)儿童工作。该进程的输出实际上保存在子作业的单独输出缓冲区中,并且可以从那里访问。您可以对一组输出使用Write-Verbose,对另一组使用Write-Warning,并分别从详细和警告流中读回:

$computer=Get-Content "serverList.txt"
$jobArray=@()
$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
}

编辑:针对所有本地工作进行了更新。