进程运行时 Powershell 尾部日志记录到控制台

问题描述 投票:0回答:2

我有一个将输出发送到日志文件的进程。我想编写一个 Powershell 脚本来启动此过程,等待它完成,并在其运行时将其日志文件实时跟踪到控制台。

我试过这个:

$procs = Start-Process "some_process.exe"
$logjob = Start-Job -Arg "some_logfile.log" -ScriptBlock {
    param($file)    
    Get-Content $file -wait | foreach { Write-Host($_) }
}
$procs | Wait-Process
$logjob | Stop-Job

...以及其他类似的安排,使用工作。但看起来作业的输出只有在作业停止后才可用,或者通过从中发送“事件”而可用,这听起来好像它们并不是真正用于日志消息之类的快速事物(例如,大约 1 分钟内 100,000 行) ).

还有其他方法可以做到这一点吗?我的下一个选择是从

Start-Process
调用“tail”,这将完成工作(我认为 - 希望这不会有相同的“等待停止”输出行为),但感觉不对。

powershell
2个回答
2
投票

除非您从作业中检索作业输出,否则不会显示作业输出。为什么不简单地逆转你正在做的事情:将进程作为一项作业启动,并在控制台上跟踪日志文件:

$job = Start-Job -ScriptBlock { & "some_process.exe" }
Get-Content "some_logfile.log" -Wait

如果您希望尾部在进程终止时终止,您可以将这两个作业作为作业运行,并在另一个作业运行时从日志作业中检索输出:

$pjob = Start-Job -ScriptBlock { & "some_process.exe" }
$ljob = Start-Job -ScriptBlock { Get-Content "some_logfile.log" -Wait }

while ($pjob.State -eq 'Running' -and $ljob.HasMoreData) {
  Receive-Job $ljob
  Start-Sleep -Milliseconds 200
}
Receive-Job $ljob

Stop-Job $ljob

Remove-Job $ljob
Remove-Job $pjob

0
投票

我遇到了同样的问题并制定了以下解决方案:

Function Start-FileTailUntilProcessExits($FileToTail, $ProcessToWatch, $TimeoutSeconds) {
    $fs = $null
    $sr = $null
    $timeToAbort = (Get-Date).AddSeconds($TimeoutSeconds)
    $timedOut = $false
    while ($true) {
    
        if (Test-Path $FileToTail) { # Wait for file to exist
            if ($null -eq $sr) {
                $fs = New-Object IO.FileStream ($FileToTail, [IO.FileMode]::Open, [IO.FileAccess]::Read, [IO.FileShare]::ReadWrite)
                $sr = New-Object IO.StreamReader ($fs)
            }
            while ($true) { 
                $line = $sr.ReadLine()
                if ($null -eq $line) {
                    # Read as many lines as are in the file currently 
                    # and then break so we can check on the status of the process and timeout
                    # If lines are added later, the StreamReader will pick up where it left off and only log new lines.
                    break
                }
                Write-Host $line
            }
        }

        if ($ProcessToWatch.HasExited) {
            Write-Host "Process has exited, so stop tailing the log"
            break
        }

        if ((Get-Date) -gt $timeToAbort) {
            $timedOut = $true
            break
        }
    
        Start-Sleep -Seconds 1
    }

    if ($null -ne $sr) {
        $sr.Dispose()
    }
    if ($null -ne $fs) {
        $fs.Dispose()
    }

    if ($timedOut) {
        Write-Error "Process timed out"
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.