2012-03-18 1 views
3

Я хотел бы побывать во время моих фоновых заданий (начато с start-job) и вывести их после x секунд. Мне трудно, однако, следить за временем работы на каждом отдельном задании (я запускаю aprox 400 заданий).Управление временем работы фоновых заданий. Сроки, если они не завершены через x секунд,

Желательно, чтобы был выход из задания и установить его на failed, если нет completed через X секунд, но я не нахожу параметр timeout.

Что было бы хорошим способом отслеживать индивидуальное время выполнения заданий?

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

Редактировать Спасибо всем за плодотворную дискуссию и большое вдохновение на эту тему!

+1

Возможно, я бы придумал что-то вроде решения HashTable, упомянутого в последнем абзаце. Кажется, хорошая идея. –

ответ

3

Вы можете использовать хэш-таблицу таймеров:

$jobtimer = @{} 

foreach ($job in $jobs){ 
    start-job -name $job -ScriptBlock {scriptblock commands} 
    $jobtimer[$job] = new-object [diagnostics.stopwatch]::startnew() 
    } 

Время работы каждого задания будет в $ jobtimer [$ job] .elapsed

+0

Это прекрасно. Однако у меня возникают проблемы с ссылкой на значения напрямую, не задавая их переменной. Как получилось 'get-job | Еогеасп { эхо $ jobtimer [$ _ имя.] .elapsed.totalseconds } ' не работает, но ' $ jobtimer [4] .elapsed.totalseconds' работает? – Sune

2

Вы можете указать опцию тайм-аута Wait-Job:

-Timeout

Определяет максимальное время ожидания для каждого фонового задания в секундах. По умолчанию, -1, ожидает завершения задания, независимо от того, как долго он проходит . Время начинается, когда вы отправляете команду Wait-Job, а не команду Start-Job.

Если это время превышено, завершение ожидания завершается, и командная строка возвращает, даже если задание все еще запущено. Не отображается сообщение об ошибке .

Вот пример кода:

Эта часть просто делает несколько тестовых заданий:

Remove-Job -Name * 
$jobs = @() 
1..10 | % { 
    $jobs += Start-Job -ScriptBlock { 
     Start-Sleep -Seconds (Get-Random -Minimum 5 -Maximum 20) 
    } 
} 

Переменная $timedOutJobs содержит задания, которые истекло. Затем вы можете перезапустить их или что у вас есть.

$jobs | Wait-Job -Timeout 10 
$timedOutJobs = Get-Job | ? {$_.State -eq 'Running'} | Stop-Job -PassThru 
+0

Это была моя первая мысль, но одна проблема с Wait-Job заключается в том, что она блокирует.Если скрипт может быть полностью заблокирован, а 400 - это завершение или тайм-аут, то это сработает. Существует также неявное предположение об использовании Wait-Job Timeout, что все задания начинаются в более или менее одинаковое время. –

+0

@ KeithHill Sune разрабатывает этот скрипт с помощью SO за последние пару недель LOL. Один из ранних вопросов касался того, как дросселировать рабочие места. Я не думаю, что 400 будет работать одновременно. –

+0

Вы правы @AndyArismendi! Я занимаюсь работой. В настоящее время работает только 20 (я обнаружил, что это приятное сладкое пятно). Если в конце сценария (или где-нибудь в скрипте) я выполняю функцию ожидания, сценарий будет повторно отправлять ВСЕ заданные задания, которые были исчерпаны. Мне нужно ограничить это до уровня дроссельной заслонки. Я думаю, что мне нужно сделать тест против хэш-таблицы в моем цикле foreach. Спасибо в любом случае :) :) – Sune

3

Просто ходить по списку запущенных заданий и остановить всех, которые пробегают мимо вашего тайм-аут спецификации, например:

 
$timeout = [timespan]::FromMinutes(1) 
$now = Get-Date 
Get-Job | Where {$_.State -eq 'Running' -and 
       (($now - $_.PSBeginTime) -gt $timeout)} | Stop-Job 

BTW есть дополнительные свойства к объекту работы, чем форматирование по умолчанию отображается, например:

 
3 > $job | fl * 


State   : Running 
HasMoreData : True 
StatusMessage : 
Location  : localhost 
Command  : Start-sleep -sec 30 
JobStateInfo : Running 
Finished  : System.Threading.ManualResetEvent 
InstanceId : de370ea8-763b-4f3b-ba0e-d45f402c8bc4 
Id   : 3 
Name   : Job3 
ChildJobs  : {Job4} 
PSBeginTime : 3/18/2012 11:07:20 AM 
PSEndTime  : 
PSJobType  : BackgroundJob 
Output  : {} 
Error   : {} 
Progress  : {} 
Verbose  : {} 
Debug   : {} 
Warning  : {} 
+1

Psbegintime - именно то, что я ищу! Но я не могу его найти. Вы используете V2 или V3? – Sune

+0

Запуск V3 на данный момент. Если у V2 нет этого поля, то да, просто создайте хэш-таблицу, чтобы сопоставить объект задания (или id) с меткой времени, созданной при создании задания. –

+0

Я нахожусь на бета-версии Win8 (PSv3), и у меня нет свойств Ps *:/'(Start-Job -ScriptBlock {gp} | gm -MemberType Свойство Ps *). Count'' '' '' ' , –

Смежные вопросы