如何在PowerShell中写入标准错误?

时间:2011-02-14 22:45:22

标签: powershell powershell-v2.0 stderr

我无法弄清楚如何回显标准错误流并重定向可执行文件的错误流。

我来自Bourne shellKorn shell背景,我将使用它;

# Write to stderr
echo "Error Message!" >&2

# Redirect stderr to file
/do/error 2>/tmp/err.msg

3 个答案:

答案 0 :(得分:39)

使用Write-Error写入stderr。要将stderr重定向到文件,请使用:

 Write-Error "oops" 2> /temp/err.msg

 exe_that_writes_to_stderr.exe bogus_arg 2> /temp/err.msg

请注意,PowerShell会将错误写为错误记录。如果你想避免错误记录的详细输出,你可以自己写出错误信息:

PS> Write-Error "oops" -ev ev 2>$null
PS> $ev[0].exception
oops

-EV-ErrorVariable的缩写(别名)。任何错误都将存储在此参数的参数所指定的变量中。除非我们将错误重定向到$null

,否则PowerShell仍会将错误报告给控制台

答案 1 :(得分:31)

你可能想要这个:

$host.ui.WriteErrorLine('I work in any PowerShell host')

您可能还会看到以下内容,但它假定您的PowerShell主机是控制台 窗口/设备,所以我认为它不太有用:

[Console]::Error.WriteLine('I will not work in the PowerShell ISE GUI')

答案 2 :(得分:26)

注意:

  • 当从那里调用PowerShell脚本时,这个答案是关于外部世界 的角度写入stderr;答案是从 Windows shell cmd.exe的角度编写的,当与PowerShell结合使用时,它同样适用于 Unix shell,例如bash

  • 相比之下,来自 Powershell 中的,您应该使用Write-Error,如Keith Hill's answer中所述。

    < / LI>
  • 可悲的是,没有统一方法可以在 PowerShell 中的中使用在外面 - 请参阅我的this answer进行讨论。


添加到@Chris Sear's great answer

虽然$host.ui.WriteErrorLine应该在所有主机中都有效,但在通过cmd.exe 调用时(默认情况下)不会写入stderr,例如来自批处理文件。 相比之下, [Console]::Error.WriteLine 总是

所以如果你想编写一个PowerShell脚本,在从cmd.exe 调用时在输出流方面很好地发挥作用,请使用以下函数Write-StdErr,它使用{ {1}} 在常规PS / [Console]::Error.WriteLine主机(控制台窗口)中,以及cmd.exe,否则:

$host.ui.WriteErrorLine

可选背景信息:

在内部,PowerShell比传统输出流(stdout和stderr)更多,并且它们的计数随着时间的推移而增加(以<# .SYNOPSIS Writes text to stderr when running in a regular console window, to the host''s error stream otherwise. .DESCRIPTION Writing to true stderr allows you to write a well-behaved CLI as a PS script that can be invoked from a batch file, for instance. Note that PS by default sends ALL its streams to *stdout* when invoked from cmd.exe. This function acts similarly to Write-Host in that it simply calls .ToString() on its input; to get the default output format, invoke it via a pipeline and precede with Out-String. #> function Write-StdErr { param ([PSObject] $InputObject) $outFunc = if ($Host.Name -eq 'ConsoleHost') { [Console]::Error.WriteLine } else { $host.ui.WriteErrorLine } if ($InputObject) { [void] $outFunc.Invoke($InputObject.ToString()) } else { [string[]] $lines = @() $Input | % { $lines += $_.ToString() } [void] $outFunc.Invoke($lines -join "`r`n") } } 为例,并在{{ 3}};请注意,链接页面尚未反映PowerShell v5中引入的Get-Help about_Redirection的流Write-Warning "I'll go unheard." 3> $null

当与外界交互时,PowerShell必须非传统输出流映射到stdout和stderr。

然而,奇怪的是,PowerShell默认情况下会在调用时将所有的所有流(包括6Write-Host输出)发送到 stdout 来自$host.ui.WriteErrorLine() ,即使将PowerShell的错误流映射到stderr也是合乎逻辑的选择。此行为自(至少)v2起生效,并且从v5.1开始仍然适用(并且由于向后兼容性原因可能不会更改)。

如果您从cmd.exe 调用,则可以使用以下命令进行验证:

cmd.exe

该命令写入所有PowerShell输出流(当您在PowerShell-v5之前的版本上运行时,您将看到与powershell -noprofile -command "'out'; Write-Error 'err'; Write-Warning 'warn'; Write-Verbose -Verbose 'verbose'; $DebugPreference='Continue'; write-debug 'debug'; $InformationPreference='Continue'; Write-Information 'info'; Write-Host 'host'; $host.ui.WriteErrorLine('uierr'); [Console]::Error.WriteLine('cerr')" >NUL 相关的其他错误消息,该消息是在PowerShell v5中引入的)并具有{ {1}}仅将标准输出重定向到Write-Information(即抑制标准输出; cmd.exe)。

除了NUL(来自>NUL,直接写入stderr)之外,您将看到 no 输出 - 所有PowerShell的流都被发送到stdout。

或许更奇怪的是, 可以捕获PowerShell的错误流,但只能重定向

如果您将上面的cerr更改为[Console]::Error.WriteLine(),那么它将独占PowerShell的错误流>NUL输出,这些输出将被抑制;当然,与任何重定向一样,您也可以将其发送到文件。 (如上所述,2>NUL 总是输出到stderr,无论后者是否被重定向。)

提供更具针对性的示例(同样,从$host.ui.WriteErrorLine()运行):

[Console]::Error.WriteLine()]

以上仅输出cmd.exe - powershell -noprofile -command "'out'; Write-Error 'err'" 2>NUL 的输出被抑制。

总结

  • 没有任何(out)重定向或只使用 stdout 重定向(Write-Errorcmd.exe), PowerShell将所有的输出流发送到 stdout

  • 使用 stderr 重定向(>...),PowerShell 有选择地错误流发送到 stderr (无论stdout是否也被重定向)。

  • 作为推论,以下常见习语按预期工作:
    1>... 正如人们所料,这不会在将 stderr 输出打印到终端时仅将 stdout 发送到文件2>...;相反,你必须使用
    powershell ... >data-output.txt

接下来 PowerShell知道data-output.txt的重定向并故意调整其行为 。 (从powershell ... >data-output.txt 2>err-output.tmp; type err-output.tmp >&2; del err-output.tmp 控制台中生成彩色输出的PowerShell中也可以看出这一点,同时在将输出重定向到文件时剥离颜色代码。)