【问题标题】:Powershell Get-Content with Wait flag and IOErrors带有等待标志和 IOErrors 的 Powershell 获取内容
【发布时间】:2017-10-05 12:01:01
【问题描述】:

我有一个 PowerShell 脚本,它以“即发即弃”的方式生成 x 个其他 PowerShell 脚本。

为了跟踪我刚刚启动的所有脚本的进度,我创建了一个临时文件,让所有脚本都以 json 格式编写日志消息以报告进度。

然后我在父脚本中使用Get-Content -Wait 监控该日志文件。每当我在日志文件中收到一行时,我都会解析 json 并更新一组对象,然后使用Format-Table 显示这些对象。这样我就可以看到不同的脚本在它们的过程中有多远,以及它们是否在特定步骤中失败。效果很好……差不多。

我一直遇到 IOErrors,因为有太多脚本正在访问日志文件,而当这种情况发生时,脚本就会中止,我会丢失有关正在发生的事情的所有信息。

我将能够忍受生成的脚本运行到 IOError,因为它们只是继续,然后我只是捕获下一条消息。我可以忍受一些消息丢失,因为这不是审核日志,而只是进度日志。

但是当跟踪日志的脚本崩溃时,我就会失去洞察力。

我尝试将其包装在 Try/Catch 中,但这无济于事。我尝试在 Try/Catch 中设置-ErrorAction Stop,但仍然没有发现错误。

我的脚本如下所示:

function WatchLogFile($statusFile)
{
    Write-Host "Tailing statusfile: $($statusFile)"
    Write-Host "Press CTRL-C to end."
    Write-Host ""
    Try {
    Get-Content $statusFile -Force -Wait | 
        ForEach { 
            $logMsg = $_ | ConvertFrom-JSON
            #Update status on step for specific service
            $svc = $services | Where-Object {$_.Service -eq $logMsg.Service}
            $svc.psobject.properties[$logMsg.step].value = $logMsg.status

            Clear-Host
            $services | Format-Table -Property Service,Old,New,CleanRepo,NuGet,Analyzers,CleanImports,Build,Invoke,Done,LastFailure
        } -ErrorAction Stop
    } Catch {
        WatchLogFile $statusFile
    }
}

在生成的脚本中更新是这样写的

Add-Content $statusFile $jsonLogMessage

是否有一种简单的方法可以添加重试,或者如何确保我的脚本能够在文件锁定中幸存下来?

【问题讨论】:

  • 你为什么不使用 Jobs?
  • 我不知道...为什么我不使用作业?该脚本不是在服务器上运行,而是在桌面上运行。我以前没有使用过 PowerShell 作业,所以不知道这可能是一种方法。在这方面,我应该特别关注乔布斯的哪些方面?
  • 这是一个我认为对你有帮助的话题。类型:PS:> help about_jobs
  • 似乎我无法从作业中获取正在运行的更新。我只能在完成后获得输出。对吗?

标签: powershell logging ioerror


【解决方案1】:

正如@ChiliYago 指出的那样,我应该使用工作。这就是我现在所做的。我必须弄清楚如何从许多脚本中获取输出。

所以我确实将我所有的工作添加到了一系列工作中,并像这样监控它们。请注意,如果您的脚本在您调用 Receive-Job 后有多个输出,您可能会收到多行。请务必使用您作为作业执行的脚本中的Write-Output

$jobs=@()
foreach ($script in $scripts)
{
    $sb = [scriptblock]::create("$script $(&{$args} @jobArgs)")
    $jobs += Start-Job -ScriptBlock $sb
}

while ($hasRunningJobs -gt 0)
{
    $runningJobs = $jobs | Where-Object {$_.State -eq "Running"} | measure
    $hasRunningJobs = $runningJobs.Count

    foreach ($job in $jobs)
    {
        $outvar = Receive-Job -Job $job
        if ($outvar)
        {
            $outvar -split "`n" | %{ UpdateStatusTable $_} 
        }
    }
}

Write-Host "All scripts done."

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多