Как убить основную \ родительскую задачу через фоновое задание? - PullRequest
0 голосов
/ 23 апреля 2019

У меня есть требование, когда мне нужно убить \ остановить основное задание, если оно выполнялось долгое время. Я думаю о создании фоновой работы, которая отслеживает время и убивает основную работу после тайм-аута с соответствующим сообщением, но я не уверен, как это сделать.

Как то так ..

    function Kill-MainTask{
      $sb = { 
      Start-Sleep -Seconds 5
      throw "main task should end"  
       }
      $job1 = Start-Job -ScriptBlock $sb 
      Write-Host "main task running"
      Start-Sleep -Seconds 10
      #This statement should not run
      Write-Host "main task not finished"
    }
    Kill-MainTask

Когда я вызываю функцию Kill-MainTask, она должна вывести «mian task running», но через 5 секунд должна сработать.

1 Ответ

0 голосов
/ 24 апреля 2019

Существует несколько примеров, показывающих, как использовать этот основной и дочерний сценарий мониторинга рабочих мест. Смотрите ниже пример и ссылки на ресурсы.

Отслеживание хода выполнения задания PowerShell

Быстрый совет, чтобы узнать, что делают ваши фоновые задания

Пример:

Это простой скрипт, который создает 5 фоновых заданий (как определяется $ Num). После отправки мы начнем мониторинг прогресс в работе. Мы определяем $ TotProg как 0 для начала, а затем запрашиваем StatusDescription-

и так как это возвращает массив, мы хотим только последний элемент, следовательно, ссылка на -1 элемент - и добавьте его к нашему $ TotProg. После этого мы проверяем, больше ли $ TotProg чем 0 (в противном случае вы получите ошибку деления на ноль), покажите наш прогресс бар, подождите несколько секунд и повторите цикл. Идите вперед и запустите код (не проходите через это в ISE, чтобы действительно видеть то, что я имею в виду, у вас есть просто запустить его).

$Num = 5

$Jobs = @()
ForEach ($Job in (1..$Num))
{   $Jobs += Start-Job -ScriptBlock { 
        $Count = 1
        Do {
            Write-Progress -Id 2 -Activity "Background Job" -Status $Count -PercentComplete 1
            $Count ++
            Start-Sleep -Seconds 4
        } Until ($Count -gt 5)
    }
}
$Total = $Num * 5

Write-Progress -Id 1 -Activity "Watching Background Jobs" -Status "Waiting for background jobs to started" -PercentComplete 0
Do {
    $TotProg = 0
    ForEach ($Job in $Jobs)
    {   Try {
            $Info = 
            $TotProg += ($Job | Get-Job).ChildJobs[0].Progress.StatusDescription[-1]
        }
        Catch {
            Start-Sleep -Seconds 3
            Continue
        }
    }
    If ($TotProg)
    {   Write-Progress -Id 1 -Activity "Watching Background Jobs" -Status "Waiting for background jobs to complete: $TotProg of $Total" -PercentComplete (($TotProg / $Total) * 100)
    }
    Start-Sleep -Seconds 3
} Until (($Jobs | Where State -eq "Running").Count -eq 0)

$Jobs | Remove-Job -Force

Write-Progress -Id 1 -Activity "Watching Background Jobs" -Status "Completed!  $Total of $Total" -PercentComplete 100
Start-Sleep -Seconds 1
Write-Progress -Id 1 -Activity "Watching Background Jobs" -Status "Completed!  $Total of $Total" -Completed

Или этот подход

Создание функции времени ожидания в сценариях PowerShell

# define a timeout
$Timeout = 10 ## seconds

# Code for the scriptblock
$jobs = Get-Job
$Condition = {param($jobs) 'Running' -notin $jobs.State }
$ConditionArgs = $jobs

# define how long in between checks
$RetryInterval = 5

# Start the timer
$timer = [Diagnostics.Stopwatch]::StartNew()

# Invoke code actions
while (($timer.Elapsed.TotalSeconds -lt $Timeout) -and (& $Condition $ConditionArgs)) {

    ## Wait a specific interval
    Start-Sleep -Seconds $RetryInterval

    ## Check the time
    $totalSecs = [math]::Round($timer.Elapsed.TotalSeconds,0)
    Write-Verbose -Message "Still waiting for action to complete after [$totalSecs] seconds..."
}


# The action either completed or timed out. Stop the timer.
$timer.Stop()

# Return status of what happened
if ($timer.Elapsed.TotalSeconds -gt $Timeout) 
{ throw 'Action did not complete before timeout period.' } 
else 
{ Write-Verbose -Message 'Action completed before the timeout period.'  }
...