1

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

我想在 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 不返回任何变量/对象。

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

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

4

2 回答 2

2

Receive-Job does not get any results because Write-Host is used which is not a standard output. Replace the line Write-Host "Unexpected CPU Usage" -ForegroundColor Red with "Unexpected CPU Usage" and Receive-Job should start to receive the messages. Use Write-Host -ForegroundColor Red in the very end of your script when processing Receive-Job.

Also, I would recommend to take a look at the module SplitPipeline which is specifically designed for such tasks. Your script can use the command Split-Pipeline and its code will be reduced to minimum:

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
}
于 2013-11-21T08:54:29.957 回答
0

Every job has at least (an normally only one) child jobs. The output of the process is actually held in separate output buffers of the child jobs, and can be accessed from there. You can use Write-Verbose for one set of output, and Write-Warning for another, and read it back from the Verbose and Warning streams separately:

$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
}

Edit: updated for all local jobs.

于 2013-11-21T11:37:44.840 回答