powershell - 带有 Invoke-Expression 的 powershell 的标准错误和标准输出没有输出或错误

标签 powershell stdout stderr

我试图从运行 java 进程中获取 stdoutstderr,并看到了一种看似简单、很酷的方法,但它不起作用:

$command = "java -jar secretserver-jconsole.jar -s 123456 Password"
Invoke-Expression $command -OutVariable output -ErrorVariable errors
Write-Host "stdout: $output"
Write-Host "stderr: $errors"
$output$errors 不显示任何内容。

我现在正在使用:
$output = cmd /c $command

这确实给了我一些 stdout ,但这并不理想,因为我想要 $error 消息。

我什至尝试了这种精心设计的方法,但它似乎并没有运行我认为的进程,因为它几乎立即返回,而且我知道几秒钟的正常进程任务。它也没有显示输出或错误:
$psi = New-object System.Diagnostics.ProcessStartInfo 
$psi.CreateNoWindow = $true 
$psi.UseShellExecute = $false 
$psi.RedirectStandardOutput = $true 
$psi.RedirectStandardError = $true 
$psi.FileName = 'java' 
$psi.Arguments = @("-jar","secretserver-jconsole.jar","-
s","123456","Password") 
$process = New-Object System.Diagnostics.Process 
$process.StartInfo = $psi 
[void]$process.Start()
$output = $process.StandardOutput.ReadToEnd() 
$process.WaitForExit()
Write-Host "stdout: $output"
(tried: adding:
do

    $process.StandardOutput.ReadLine()
}
while (!$process.HasExited)

最佳答案

注意:下面的解决方案假定一个行为良好的外部实用程序:一个将数据发送到 stdout,并将错误消息发送到 stderr。如果给定的实用程序意外地将错误消息发送到 stdout,就像 OP 的情况一样,您必须自己解析 stdout 输出以提取错误消息。

$stdout = java -jar secretserver-jconsole.jar -s 123456 Password 2>($tmpFile=New-TemporaryFile)
$stderr = Get-Content $tmpFile; Remove-Item $tmpFile
New-TemporaryFile 需要 PSv5,但您可以在早期版本中使用 [io.path]::GetTempFileName()

请注意,$stdout$stderr 都将包含一个字符串数组,每个项目代表一个输出行。

外部实用程序的退出代码反射(reflect)在 PowerShell 的自动 $LASTEXITCODE 变量中。

请注意,捕获 stdout 和 stderr 的组合实际上更容易:
$stdoutAndStdErr = java -jar secretserver-jconsole.jar -s 123456 Password 2>&1

注意:每个 stderr 行在结果中都表示为一个 [System.Management.Automation.ErrorRecord] 实例,但它们在字符串上下文中计算为该行的内容。

至于你尝试了什么:

通常不需要将命令存储在字符串中(因此很少需要使用 Invoke-Expression ,其使用可能存在风险)。
  • 或者:甚至直接调用外部命令行(注意 PowerShell 可能不需要的命令行解释;在 PSv3 中,--% 关闭 PowerShell 的解释 - 请参阅 Get-Help about_Parsing ),
  • 或者,如果您需要先将命令存储在变量中,请使用脚本 block ($cmd = { ... }),然后使用 &(调用运算符)或 .(点源运算符)调用它 - 前者为 PS 创建一个子范围变量,后者没有。
  • -OutVariable-ErrorVariable 通用参数仅设计用于 PowerShell 的输出流,而不是外部世界的 stdout 和 stderr。
  • PowerShell 捕获标准输出输出,就像它已发送到 PowerShell 的成功输出流一样,并将输出行视为字符串数组。
  • 标准错误输出被传递(并且不反射(reflect)在 $Error 中),但您可以使用 2>$file 将其重定向到文件,或者您可以使用 2>&1 将其合并到成功流中(在这种情况下,stderr 行均表示为 [System.Management.Automation.ErrorRecord]实例)。
  • 关于powershell - 带有 Invoke-Expression 的 powershell 的标准错误和标准输出没有输出或错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43784702/

    相关文章:

    powershell - 如何使用 Powershell 按顺序打印 PDF 文件?

    powershell - 如何在 powershell PSReadLine 模块中保存和加载历史记录?

    Python:如何窥视 pty 对象以避免阻塞?

    Linux - 将命令的 STDOUT 发送到 RSS 提要

    linux - 如何同时将 bash 输出通过管道传输到文件和终端?

    powershell - 为 cmdlet 定义创建额外的默认参数

    powershell - Azure 自动化作业共享订阅上下文

    linux - 动态地逐行解析程序输出

    python - "subprocess.Popen"- 检查成功和错误

    c - 在 Windows 平台上,C 代码中的临时重定向 stderr 为 null。