带有 Invoke-Expression 的 powershell 的 Stderr 和 stdout 没有输出或错误 [英] Stderr and stdout for powershell with Invoke-Expression has no output or errors

查看:57
本文介绍了带有 Invoke-Expression 的 powershell 的 Stderr 和 stdout 没有输出或错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试通过运行 java 进程来获取 stdoutstderr,并且看到了一种看似简单、很酷的方法,但它没有用:

I am trying to get stdout and stderr from running a java process, and saw what seemed like an easy, cool way to do it, but it did not work:

$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 不显示任何内容.

Nothing displays with $output or $errors.

我现在正在使用:

$output = cmd /c $command

这确实为我提供了一些 stdout,但它并不理想,因为我想要 $error 消息.

This does get me some stdout, but it is not ideal as I want $error message.

我什至尝试了这种精心设计的方法,但它似乎没有运行我认为的进程,因为它几乎立即返回,而且我知道正常进程任务几秒钟.它也没有显示输出或错误:

I tried even this elaborate method, but it does not even seem to run the process I think as it returns almost instantly, and I know the normal process tasks several seconds. It also shows no output or 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 输出以提取错误消息.

Note: The solution below assumes a well-behaved external utility: one that sends data to stdout, and error messages to stderr. If a given utility unexpectedly sends error messages to stdout instead, as appears to be the case for the OP, you must do your own parsing of stdout output to extract error messages.

$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().

New-TemporaryFile requires PSv5, but you can use [io.path]::GetTempFileName() in earlier versions.

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

Note that both $stdout and $stderr will contain a string array, with each item representing an output line.

外部实用程序的退出代码反映在 PowerShell 的自动 $LASTEXITCODE 变量中.

The external utility's exit code is reflected in PowerShell's automatic $LASTEXITCODE variable.

请注意,捕获 stdout 和 stderr 组合实际上更容易:

Note that capturing stdout and stderr combined is actually easier:

$stdoutAndStdErr = java -jar secretserver-jconsole.jar -s 123456 Password 2>&1

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

Note: The stderr lines are each represented as a [System.Management.Automation.ErrorRecord] instance in the result, but they evaluate to the contents of the line in a string context.

至于你尝试了什么:

通常不需要在 string 中存储命令(因此很少需要使用 Invoke-Expression,它的使用可能有风险).

There's generally no need to store a command in a string (and therefore rarely a need to use Invoke-Expression, whose use can be risky).

  • 或者:甚至直接调用外部命令行(注意 PowerShell 可能不需要的命令行解释;在 PSv3 中,--% 关闭 PowerShell 的解释 - 参见 Get-Help about_Parsing),
  • 或者,如果您需要先将命令存储在变量中,请使用脚本块 ($cmd = { ... }),然后再调用它使用 &(调用运算符)或 .(点源运算符) - 前者为 PS 变量创建一个子作用域,后者不会.
  • Either: invoke even external command lines directly (be mindful of possibly unwanted interpretation of the command line by PowerShell; in PSv3, --% turns off PowerShell's interpretation - see Get-Help about_Parsing),
  • or, if you need to store the command in a variable first, use a script block ($cmd = { ... }), and invoke it later with & (call operator) or . (dot-sourcing operator) - the former creates a child scope for PS variables, the latter does not.

-OutVariable-ErrorVariable 公共参数仅设计用于 PowerShell 的 输出流,而不是外部世界的 stdout 和 stderr.

The -OutVariable and -ErrorVariable common parameters are only designed to work with PowerShell's output streams, not the outside world's stdout and stderr.

  • PowerShell 捕获 stdout 输出,就好像它已发送到 PowerShell 的成功输出流一样,并将输出行视为字符串数组.

Stderr 输出通过(并且不会反映在 $Error 中),但您可以将其重定向到带有 2>$file 的文件,或您可以使用 2>&1 将其合并到成功流中(在这种情况下,每个 stderr 行都表示为一个 [System.Management.Automation.ErrorRecord] 实例).

Stderr output is passed through (and is not reflected in $Error), but you can redirect it to a file with 2>$file, or you can merge it into the success stream with 2>&1 (in which case the stderr lines are each represented as a [System.Management.Automation.ErrorRecord] instance).

这篇关于带有 Invoke-Expression 的 powershell 的 Stderr 和 stdout 没有输出或错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆