I would like to time my background jobs (started with start-job
) and time them out after x
seconds. I find it hard however to keep track of the running time on each separate job (I am running aprox 400 jobs).
I wish there was a way to time out the job and set it to failed
if not completed
in X seconds, but I find no timeout-parameter.
What would be a good way to track the individual run-time of the jobs?
I guess I could create a hashtable with start-time of each job and the job-id and check against the running
state and do a manual timeout, but that sounds kinda "inventing the wheel".
Any ideas?
Edit Thank you everyone for a fruitful discussion and great inspiration on this topic!
You can use a hash table of timers:
$jobtimer = @{}
foreach ($job in $jobs){
start-job -name $job -ScriptBlock {scriptblock commands}
$jobtimer[$job] = [System.Diagnostics.Stopwatch]::startnew()
}
The running time of each job will be in $jobtimer[$job].elapsed
Just walk through the list of running jobs and stop any that have run past your timeout spec e.g.:
$timeout = [timespan]::FromMinutes(1) $now = Get-Date Get-Job | Where {$_.State -eq 'Running' -and (($now - $_.PSBeginTime) -gt $timeout)} | Stop-Job
BTW there are more properties to a job object than the default formatting shows e.g.:
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 : {}
You can specify the timeout option of Wait-Job
:
-Timeout
Determines the maximum wait time for each background job, in seconds. The default, -1, waits until the job completes, no matter how long it runs. The timing starts when you submit the Wait-Job command, not the Start-Job command.
If this time is exceeded, the wait ends and the command prompt returns, even if the job is still running. No error message is displayed.
Here's some example code:
This part just makes some test jobs:
Remove-Job -Name *
$jobs = @()
1..10 | % {
$jobs += Start-Job -ScriptBlock {
Start-Sleep -Seconds (Get-Random -Minimum 5 -Maximum 20)
}
}
The variable $timedOutJobs
contains jobs that timed out. You can then restart them or what have you.
$jobs | Wait-Job -Timeout 10
$timedOutJobs = Get-Job | ? {$_.State -eq 'Running'} | Stop-Job -PassThru
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With