2012-03-18 31 views
3

我想将我的后台作业(从start-job开始)和x秒之后的时间排除在外。但是我发现很难记录每个单独作业的运行时间(我正在运行aprox 400个作业)。管理后台作业的运行时间。如果在x秒后未完成,则计时结束

我希望有一种方法来超时工作,并将其设置为failed如果不是completed在X秒内,但我找不到超时参数。

什么是追踪工作的个人运行时间的好方法?

我想我可以创建一个哈希表,每个作业的开始时间和作业ID,并检查对running状态,并进行手动超时,但这听起来有点“发明车轮”。 任何想法?

编辑 谢谢大家在这个话题上的富有成效的讨论和伟大的灵感!

+1

我可能会想出类似于您在最后一段中提到的HashTable解决方案。似乎是个好主意。 – 2012-03-18 15:30:46

回答

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 | foreach {0} $ jobtimer [$ _。name] .elapsed.totalseconds }' 不起作用,但是 '$ jobtimer [4] .elapsed.totalseconds'确实有效吗? – Sune 2012-03-19 11:42:49

2

您可以指定Wait-Job超时选项:

-Timeout

确定最长等待时间为每个后台作业,以秒计。 默认值-1等待作业完成,无论它运行多长时间。提交等待作业命令时开始计时,而不是 开始作业命令。

如果超过此时间,即使作业仍在运行,等待结束并返回命令提示符 。没有错误信息显示为 。

下面是一些示例代码:

这部分只是让一些测试工作:

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的一个问题是它阻塞了。如果脚本可以完全阻止,而OP的400个作业完成或超时,那么这将工作。在等待作业超时的使用中还有一个隐含的假设,即所有作业大致在同一时间开始。 – 2012-03-18 23:57:29

+0

@KeithHill在过去几周里,Sune一直在SO的帮助下开发这个脚本。其中一个较早的问题涉及如何扼杀工作。我不认为400会同时运行。 – 2012-03-19 00:10:19

+0

你是对的@AndyArismendi!我限制了工作......当时只跑20(我发现这是一个不错的甜点)。如果我在脚本的末尾(或脚本中的任何地方)做了一个等待工作,脚本将重新提交所有已超时的作业。我需要将此限制在我的限制级别。我想我必须在我的foreach循环中对一个哈希表进行测试。无论如何,谢谢:) :) – Sune 2012-03-19 09:24:18

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 2012-03-18 19:56:36

+0

目前运行V3。如果V2没有该字段,那么是的,只需创建一个散列表,将$ job对象(或id)映射到您在创建作业时创建的时间戳。 – 2012-03-18 23:53:09

+0

我在Win8 beta(PSv3)上,我似乎也没有Ps *属性:/'(Start-Job-ScriptBlock {gp} | gm -MemberType Property Ps *)。Count'is'0' 。 – 2012-03-19 00:16:05