gpt4 book ai didi

powershell - 将写入进度添加到 Get-Job/Wait-Job

转载 作者:行者123 更新时间:2023-12-02 18:13:45 26 4
gpt4 key购买 nike

我使用以下代码显示超时为 120 秒的 PowerShell 作业的结果。我想通过合并 Write-Progress(基于完成的作业数)来增强此代码。我尝试使用 this example然而,作为引用,当我尝试合并该代码时,进度条会在所有作业都已完成后短暂显示。

    $Jobs = @()
$ForceStoppedIds = @{}

$Jobs += Get-Job
$Jobs | Wait-Job -Timeout 120 | Out-Null
$Jobs | ?{$_.State -eq 'Running'} | Stop-Job -PassThru | %{$ForceStoppedIds[$_.Id] = $true}

foreach ($Job in $Jobs) {

$Name = $Job.Name
$Output = (Get-Job -Name $Name | Receive-Job)

if ($ForceStoppedIds.Contains($Job.Id)) {

Write-Output "$($Name) - Device unable to process request within 2 minutes"

} else {

Write-Output $Output

}

}

最佳答案

Wait-Job -Timeout 120将阻塞线程直到指定超时或所有作业完成,因此不可能同时显示进度和等待它们。

我可以想到两种选择,第一种是创建一个 proxy command/围绕此 cmdlet 的代理函数以扩展其功能。

这些博客演示了如何做到这一点:

您还可以按照 this helpful answer 中的指示进行操作.


另一种选择是定义您自己的函数,其功能与 Wait-Job 类似。但是,您可以添加一个基于 2 个条件运行的循环,而不是阻塞线程:

  • 耗时小于或等于我们作为参数传递给函数的超时(为此我们可以使用 Diagnostics.Stopwatch )。
  • 而且,作业仍在运行($jobs List<T> 仍然存在)。

注意,下面的函数应该可以在大多数情况下使用,但是仅用于演示目的,不应依赖。

首先,我们定义了一个新函数,可用于显示进度以及基于超时等待我们的作业:

using namespace System.Collections.Generic
using namespace System.Diagnostics
using namespace System.Threading
using namespace System.Management.Automation

function Wait-JobWithProgress {
[cmdletbinding()]
param(
[parameter(Mandatory, ValueFromPipeline)]
[object[]] $InputObject,

[parameter()]
[double] $TimeOut
)

begin {
$jobs = [List[object]]::new()
}

process {
foreach($job in $InputObject) {
$jobs.Add($job)
}
}

end {
$timer = [Stopwatch]::StartNew()
$total = $jobs.Count
$completed = 0.1
$expression = { $true }

if($PSBoundParameters.ContainsKey('TimeOut')) {
$expression = { $timer.Elapsed.TotalSeconds -le $TimeOut }
}

while((& $expression) -and $jobs) {
$remaining = $total - $completed
$average = $timer.Elapsed.TotalSeconds / $completed
$estimate = [math]::Round($remaining * $average)
$status = 'Completed Jobs: {0:0} of {1}' -f $completed, $total
$progress = @{
Activity = 'Waiting for Jobs'
PercentComplete = $completed / $total * 100
Status = $status
SecondsRemaining = $estimate
}
Write-Progress @progress

$id = [WaitHandle]::WaitAny($jobs.Finished, 200)
if($id -eq [WaitHandle]::WaitTimeout) {
continue
}

# output this job
$jobs[$id]
# remove this job
$jobs.RemoveAt($id)
$completed++
}

# Stop the jobs not yet Completed and remove them
$jobs | Stop-Job -PassThru | ForEach-Object {
Remove-Job -Job $_
"Job [#{0} - {1}] did not complete on time and was removed." -f $_.Id, $_.Name
} | Write-Warning
Write-Progress @progress -Completed
}
}

然后为了测试它,我们可以创建一些带有随机计时器的作业:

0..10 | ForEach-Object {
Start-Job {
Start-Sleep (Get-Random -Minimum 5 -Maximum 15)
[pscustomobject]@{
Job = $using:_
Result = 'Hello from [Job #{0:D2}]' -f $using:_
}
}
} | Wait-JobWithProgress -TimeOut 10 |
Receive-Job -AutoRemoveJob -Wait | Format-Table -AutoSize

关于powershell - 将写入进度添加到 Get-Job/Wait-Job,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71918277/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com