我正在尝试使用后台作业机制并行地对多台计算机执行cmdlet(测试连接)。下面的函数很好,直到我抛出超过649个主机名(至少在这台机器上),然后抛出异常:
PS> 。\ test.ps1。\ 650_hostnames.txt
Receive-Job : Quota violation
At H:\Development\Powershell\test.ps1:13 char:13
+ Receive-Job <<<< |
+ CategoryInfo " InvalidResult: (:) [Receive-Job], ManagementException
+ FullyQualifiedErrorId : JobStateFailed,Microsoft.PowerShell.Commands.ReceiveJobCommand
出于性能原因,我仍希望将cmdlet作为后台作业执行,但是要控制在给定时间启动的作业数。我无法控制输入,所以我可以得到几千到几百的列表。任何建议都表示赞赏!
test.ps1
$wkslist = $args[0]
function IsAlive {
param(
[Parameter(
Mandatory = $true,
Position = 0)]
$computername
)
test-connection -count 1 -ComputerName $computername -TimeToLive 30 `
-ThrottleLimit 10 -asJob |
Wait-Job |
Receive-Job |
Where-Object { $_.StatusCode -eq 0 } |
Select-Object -ExpandProperty Address
}
$ips = [System.IO.File]::ReadAllLines("$wkslist")
IsAlive -computername $ips
答案 0 :(得分:3)
看起来这与你正在使用工作的事实无关;它似乎与输入的大小传递给测试连接。我可以使用以下代码重现配额违规:
$ra = @(0..1000) | %{ $env:computername };
test-connection -computername $ra;
似乎是测试连接内部的东西,最终创建了Win32_Ping WMI对象。我也可以通过切出部分输入数组来获得代码:
$ra = @(0..1000) | %{ $env:computername };
test-connection -computername $ra[0..500];
请注意,650似乎不是一个神奇的数字 - 我可以查询多达800个主机名,而不会遇到错误。
由于异常是管理异常而不是PowerShell内部异常,我会说你已经找到了WMI的许多神奇限制之一。听起来像测试连接应该在内部管理,但事实并非如此。我已经在Connect上记录了一个问题,如果你想提出它:test-connection throws quota exception when passed large list of computernames
我会按原样尝试您的工作代码,但将主机名列表分成较小的部分:
$i = 100;
$j = 0;
while( $i -le $ra.length )
{
test-connection -computername $ra[$j..$i] ... ;
$j = $i + 1;
$i += 100;
}
答案 1 :(得分:0)
我会稍微重新调整代码,看起来像这样:
将以下代码放入根profile.ps1 c:\ windows \ system32 \ windowspowershell \ v1.0 \ profile.ps1。如果它不存在,只需创建一个文本文件并重命名即可。启动PowerShell时,默认情况下会加载此profile.ps1文件。
Function Test-Connection()
{
param(
[Parameter(Mandatory = $true,Position = 0)]$Count,
[Parameter(Mandatory= $true,Position = 1)]$IP,
[Parameter(Mandatory= $true,Position = 2)]$TTL,
[Parameter(Mandatory= $true,Position = 3)]$ThrottleLimit
)
MyCommand $Count $IP $TTL $ThrottleLimit
}
然后使用以下代码运行作业,从我的博客http://www.poshpete.com/archives/27复制我的阈值例程:
$ips = Get-Content $wkslist
ForEach($IP in $ips)
{
Threshold -MaxConcurrent 10 -PauseTime 5
Start-Job -ScriptBlock {test-connection} -ArgumentList $Count,$IP,$TTL,$ThrottleLimit -Name $IP
$CompletedJobs = Get-Job -State Completed
If(($CompletedJobs | Measure-Object).Count -gt 0)
{
ForEach($Job in $CompletedJobs)
{
$Job | Receive-Job | Where-Object { $_.StatusCode -eq 0 } | Select-Object -ExpandProperty Address
}
}
}
我正在使用get-content从文本文件中获取数据,但您也可以使用.net对象。
希望这有意义!
答案 2 :(得分:0)
在努力提高配额限制后,我意识到无论如何我需要控制功能的输入量。某人或某物将通过比配额允许的更多主机,即使您提出它或超过机器的资源。配额用于保护本地计算机和/或远程计算机免受意外和恶意的过度资源使用。这是一件好事(尽管我仍然对如何控制数字感兴趣)。
根据about_Remote_Troubleshooting帮助解决错误:
至于确定配额的来源,对我来说仍然是一个谜。当我找到主机提供程序进程的配置类_ProviderHostQuotaConfiguration时,我以为我越来越近了。此类允许在主机进程使用系统资源时设置限制。可用的不同属性是:
然而,在增加值后,我仍然收到相同的违规行为。如果有人知道要改变什么来提高可用于测试连接的主机数量,我相信该组会很感激。