Powershell Receive-Job: нарушение квоты при вызове команды в качестве задания - PullRequest
2 голосов
/ 20 января 2011

Я пытаюсь выполнить командлет (тест-соединение) для нескольких машин параллельно, используя механизм фоновых заданий.Функция ниже хороша, пока я не передам более 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

Я хотел бы по-прежнему выполнять командлет в качестве фонового задания из соображений производительности, но контролировать количество заданий, запускаемых в данный момент времени.Я не могу контролировать ввод, чтобы получить список от нескольких тысяч до нескольких сотен.Любые предложения приветствуются!

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

Ответы [ 3 ]

3 голосов
/ 20 января 2011

Похоже, это не имеет ничего общего с тем, что вы используете работу; похоже, размер входного файла передается в тестовое соединение. Я могу воспроизвести нарушение квоты с помощью этого кода:

$ra = @(0..1000) | %{ $env:computername };
test-connection -computername $ra;

Кажется, что-то внутреннее для test-connection, что в итоге создает метинки объектов WMI Win32_Ping. Я также могу заставить код работать, вырезав часть входного массива:

$ra = @(0..1000) | %{ $env:computername };
test-connection -computername $ra[0..500];

Обратите внимание, что 650 не является магическим числом - я могу запросить около 800 имен хостов, не обнаружив ошибки.

Поскольку это исключение управления, а не внутреннее исключение PowerShell, я бы сказал, что вы нашли одно из многих магических ограничений WMI. Также звучит как то, что тест-соединение должно управлять внутри, но не делает. Я зарегистрировал проблему на Connect здесь, если вы хотите, чтобы ее проголосовать: test-connection генерирует исключение квоты при передаче большого списка имен компьютеров

Я бы попробовал ваш код работы как есть, но разделил список имен хостов на более мелкие сегменты:

$i = 100;
$j = 0;
while( $i -le $ra.length )
{ 
   test-connection -computername $ra[$j..$i] ... ;
   $j = $i + 1;
   $i += 100;
}
0 голосов
/ 29 января 2011

После попытки поднять лимит квоты я понял, что мне все равно нужно контролировать количество входных данных для функции. Кто-то или что-то пропустит больше хостов, чем позволяет квота, даже если вы подняли ее, или превысите ресурсы вашей машины. Квоты используются для защиты локального компьютера и / или удаленного компьютера от чрезмерного использования ресурсов, как случайного, так и вредоносного. Это хорошо (хотя мне все еще интересно узнать, как контролировать число).

Согласно справке по устранению неполадок about_Remote_Trou:

  1. Изменить удаленную команду для соответствия квоте. (Спасибо капитан. Очевидный)
  2. Или определите источник квоты, а затем увеличьте квоту, чтобы команда могла завершиться.

Что касается определения источника квоты, для меня до сих пор остается загадкой. Я подобрался ближе, когда нашел класс конфигурации для процессов провайдера хоста _ProviderHostQuotaConfiguration. Этот класс позволяет устанавливать ограничения на использование системных ресурсов процессами хоста. Доступны следующие свойства:

  • ThreadsPerHost: определяет количество потоков, принадлежащих любому хосту
  • HandlesPerHost: определяет количество дескрипторов объектов ядра, которое может иметь каждый хост
  • ProcessLimitAllHosts: определяет общее количество процессов хоста, которые могут выполняться одновременно
  • MemoryPerHost: определяет объем приватной памяти, который может храниться на каждом хосте
  • MemoryAllHosts: определяет общий объем личной памяти (в байтах), который может храниться всеми хостами

Однако после увеличения значений я все еще получил то же нарушение. Если кто-то знает, что конкретно нужно изменить, чтобы увеличить количество хостов, которые можно использовать против Test-Connection, я уверен, что группа это оценит.

0 голосов
/ 20 января 2011

Я бы немного посмотрел на реструктуризацию кода, чтобы это выглядело так:

Поместите следующий код в корневой каталог profile.ps1 c: \ windows \ system32 \ windowspowershell \ v1.0 \ profile.ps1. Если он не существует, просто создайте текстовый файл и переименуйте его. Этот файл profile.ps1 будет загружен по умолчанию при запуске powershell.

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.

Надеюсь, это имеет смысл!

...