Note:我正在尝试跑步packer.exe
作为解决特定问题的后台进程azure-arm
构建器,我需要观察输出。我没有使用
Start-Process
因为我不想使用中间文件来使用输出。
我设置了以下代码packer.exe
在后台运行,以便我可以使用其输出并对特定日志消息采取行动。这是一个较大脚本的一部分,但这是有问题的部分,其行为不正确:
$builderDir = ( Split-Path -Parent $PSCommandPath )
Push-Location $builderDir
# Set up the packer command to run asynchronously
$pStartProps = @{
FileName = ( Get-Command -CommandType Application packer ).Source
Arguments = "build -var-file ""${builderDir}\win-dev.pkrvars.hcl"" -only ""azure-arm.base"" ."
UseShellExecute = $false
RedirectStandardOutput = $true
RedirectStandardError = $false
LoadUserProfile = $true
}
$pStartInfo = New-Object ProcessStartInfo -Property $pStartProps
$p = [Process]::Start($pStartInfo)
while ( $null -ne ( $output = $p.StandardOutput.Readline() ) -or !$p.HasExited ) {
# Do stuff
}
基本上,( $output = $p.StandardOutput.Readline() )
的一部分while
条件似乎一直处于挂起状态,直到有更多输出可供读取。我不知道为什么会这样,因为StreamReader.Readline()
应该返回要读取的下一行,或者null https://learn.microsoft.com/en-us/dotnet/api/system.io.streamreader.readline?view=netcore-3.1#returns如果没有更多的输出。关于我期望获得的日志消息,我对此进行了相当多的处理,因此在没有进一步的输出可供使用时读取 STDOUT 时阻塞会使脚本变得无用。当它在前台执行其他操作时packer.exe
继续执行。
我可以在调试器中确认Readline()
确实读取空行(值""
)好吧,这似乎是在还没有进一步的输出可供消耗时发生的。这可能是切线的,但这也会导致调试器出错。
发生此问题时,VSCode 调试器会使用
$output = $p.StandardOutput.Readline()
突出显示几秒钟,然后调试器停止(一切都消失,不再有变量跟踪等),直到Readline()
停止阻塞并继续执行,此时调试器似乎重新初始化了跟踪的变量、监视的表达式等。因此,当发生这种情况时,我根本无法使用调试器。即便是
PowerShell Integrated Console
(与调试器一起使用的)挂起,我无法输入任何内容。
对于完整的上下文,此脚本的目标是让packer.exe
当我不断循环时做它的事情:
- 显示更多输出
packer.exe
- 检查是否存在特定日志消息
- Give
packer.exe
有一点时间尝试自己做需要做的事情
- If it waits too long, I execute a script against the node being since what
packer.exe
should have done on its own likely failed
- 我在用
Invoke-AzVMRunCommand
做到这一点,这在国家是做不到的packer.exe
对于我正在解决的问题。它必须在带外执行packer.exe
自己运行。
- 应用解决方法后,构建将继续,我只需继续转发输出
packer.exe
到控制台直到进程退出
但由于脚本在没有输出时挂起,因此步骤 4 永远不会起作用,因为我必须给加壳器时间来尝试自己完成配置,这也是我首先将其一起破解的全部原因。
Why is Readline()
堵在这里?我做错了什么吗?无论我在 Windows PowerShell 还是 PowerShell Core 中运行脚本,都会出现此行为。