如何在 PowerShell 中写入标准错误?
我无法弄清楚如何回显标准错误流并重定向可执行文件的错误流。
我来自 Bourne shell 和 Korn shell 背景,我会使用它;
# Write to stderr
echo "Error Message!" >&2
# Redirect stderr to file
/do/error 2>/tmp/err.msg
I'm having trouble figuring out how to both echo to the standard error stream and redirect the error stream of an executable.
I have come from a Bourne shell and Korn shell background, of which I would use;
# Write to stderr
echo "Error Message!" >&2
# Redirect stderr to file
/do/error 2>/tmp/err.msg
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
使用
Write-Error
写入stderr。要将 stderr 重定向到文件,请使用:或
请注意,PowerShell 将错误写入错误记录。如果您想避免错误记录的详细输出,您可以自己写出错误信息,如下所示:
-EV
是-ErrorVariable
的缩写(别名)。任何错误都将存储在此参数的参数命名的变量中。 PowerShell 仍会向控制台报告错误,除非我们将错误重定向到$null
。Use
Write-Error
to write to stderr. To redirect stderr to file use:or
Note that PowerShell writes errors as error records. If you want to avoid the verbose output of the error records, you could write out the error info yourself like so:
-EV
is short (an alias) for-ErrorVariable
. Any errors will be stored in the variable named by the argument to this parameter. PowerShell will still report the error to the console unless we redirect the error to$null
.注意:
这个答案是关于当从外部世界调用 PowerShell 脚本时从外部世界的角度写入 stderr 的内容;虽然答案是从 Windows shell
cmd.exe
的角度编写的,但它同样适用于 Unix shell,例如bash
与 PowerShell Core 结合使用。相比之下,在 Powershell 中,您应该使用
Write-Error
,如 基思·希尔的回答。遗憾的是,没有一种统一的方法可以同时在PowerShell内部和外部工作 -请参阅此我的回答供讨论。
添加到 @Chris Sear 的精彩答案:
虽然
$host.ui.WriteErrorLine
应该在所有主机中工作,但在通过cmd.exe
调用时不会(默认情况下)写入 stderr ,例如来自批处理文件。相比之下,
[Console]::Error.WriteLine
总是。因此,如果您想编写一个在从
cmd.exe 调用时在输出流方面表现良好的 PowerShell 脚本
,请使用以下函数Write-StdErr< /code>,它使用
[Console]::Error.WriteLine
在常规 PS /
cmd.exe
主机(控制台窗口)中,以及$host.ui.WriteErrorLine
否则:可选背景信息:如何PowerShell CLI 的输出流可以被外部调用者看到:
在内部,PowerShell 比传统输出流(stdout 和 stderr)更多,并且它们的数量随着时间的推移而增加(尝试
Write-Warning“I '会闻所未闻。" 3> $null
作为示例,并在Get-Help about_Redirection
。与外界交互时,PowerShell 必须映射非传统输出流然而
,奇怪的是,PowerShell 默认发送其所有流(包括 Write-Host 和 $host.ui.WriteErrorLine()) 输出)到 stdout,当从
cmd.exe
调用时,即使将 PowerShell 的错误流映射到 stderr 是合乎逻辑的选择。此行为从(至少)v2 开始生效,并且从 v5.1 起仍然适用(并且由于向后兼容性的原因可能不会改变 - 请参阅 GitHub 问题 #7989)。如果您从
cmd.exe
调用它,您可以使用以下命令验证这一点:该命令写入所有 PowerShell 输出流(当您在 PowerShell 之前版本上运行时) v5 版本中,您将看到与
Write-Information
相关的附加错误消息,该消息是在 PowerShell v5 中引入的)并且具有cmd.exe
重定向仅 stdout< /em> 到NUL
(即抑制 stdout 输出;>NUL
)。除了
cerr
(来自[Console]::Error.WriteLine()
,直接写入 stderr)之外,您将看到没有输出 - 所有PowerShell 的流被发送到标准输出。也许更奇怪的是,可以捕获 PowerShell 的错误流,但只能通过重定向:
如果您更改
>NUL
到上面的2>NUL
,它只是 PowerShell 的错误流 和$host.ui.WriteErrorLine()
输出压制;当然,与任何重定向一样,您也可以将其发送到文件。(如上所述,
[Console]::Error.WriteLine()]
总是输出到stderr,无论后者是否被重定向。)举一个更有针对性的例子(再次,从
cmd.exe
运行):以上仅输出
out
-Write-Error
的输出被抑制。总结:
没有任何(
cmd.exe
)重定向或仅stdout重定向(< code>>... 或1>...
),PowerShell 将其所有输出流发送到stdout。< /p>通过stderr重定向(
2>...
),PowerShell选择性将其错误流发送到stderr(无论 stdout 是否也被重定向)。作为推论,以下常见习惯用法无法按预期工作:
powershell ...>data-output.txt
正如人们所期望的那样,这不会在将 stderr 输出打印到终端时仅将 stdout 发送到文件
data-output.txt
;相反,你必须使用powershell ... >data-output.txt 2>err-output.tmp;输入 err-output.tmp >&2;删除错误输出.tmp
由此可见,PowerShell 能够识别
cmd.exe
的重定向并有意调整其行为。(这也可以从 PowerShell 在
cmd.exe
控制台 中生成彩色输出中看出,同时在输出重定向到文件时剥离颜色代码。 )Note:
This answer is about writing to stderr from the perspective of the outside world when a PowerShell script is called from there; while the answer is written from the perspective of the Windows shell,
cmd.exe
, it equally applies to Unix shells such asbash
when combined with PowerShell Core.By contrast, from within Powershell, you should use
Write-Error
, as explained in Keith Hill's answer.Sadly, there is no unified approach that will work from both within PowerShell and from the outside - see this answer of mine for a discussion.
To add to @Chris Sear's great answer:
While
$host.ui.WriteErrorLine
should work in all hosts, it doesn't (by default) write to stderr when invoked viacmd.exe
, such as from a batch file.[Console]::Error.WriteLine
, by contrast, always does.So if you want to write a PowerShell script that plays nicely in terms of output streams when invoked from
cmd.exe
, use the following function,Write-StdErr
, which uses[Console]::Error.WriteLine
in the regular PS /
cmd.exe
host (console window), and$host.ui.WriteErrorLine
otherwise:Optional background information: How the PowerShell CLI's output streams are seen by outside callers:
Internally, PowerShell has more than the traditional output streams (stdout and stderr), and their count has increased over time (try
Write-Warning "I'll go unheard." 3> $null
as an example, and read more atGet-Help about_Redirection
.When interfacing with the outside world, PowerShell must map the non-traditional output streams to stdout and stderr.
Strangely, however, PowerShell by default sends all its streams (including
Write-Host
and$host.ui.WriteErrorLine()
output) to stdout when invoked fromcmd.exe
, even though mapping PowerShell's error stream to stderr would be the logical choice. This behavior has been in effect since (at least) v2 and still applies as of v5.1 (and probably won't change for reasons of backward compatibility - see GitHub issue #7989).You can verify this with the following command, if you invoke it from
cmd.exe
:The command writes to all PowerShell output streams (when you run on a pre-PowerShell-v5 version, you'll see an additional error message relating to
Write-Information
, which was introduced in PowerShell v5) and hascmd.exe
redirect stdout only toNUL
(i.e., suppress stdout output;>NUL
).You will see no output except
cerr
(from[Console]::Error.WriteLine()
, which writes directly to stderr) - all of PowerShell's streams were sent to stdout.Perhaps even more strangely, it is possible to capture PowerShell's error stream, but only with a redirection:
If you change
>NUL
to2>NUL
above, it is exclusively PowerShell's error stream and$host.ui.WriteErrorLine()
output that will be suppressed; of course, as with any redirection, you can alternatively send it to a file.(As stated,
[Console]::Error.WriteLine()]
always outputs to stderr, whether the latter is redirected or not.)To give a more focused example (again, run from
cmd.exe
):The above only outputs
out
-Write-Error
's output is suppressed.To summarize:
Without any (
cmd.exe
) redirection or with only a stdout redirection (>...
or1>...
), PowerShell sends all its output streams to stdout.With a stderr redirection (
2>...
), PowerShell selectively sends its error stream to stderr (irrespective of whether stdout is also redirected or not).As a corollary, the following common idiom does not work as expected:
powershell ... >data-output.txt
This will not, as one might expect, send only stdout to file
data-output.txt
while printing stderr output to the terminal; instead, you'd have to usepowershell ... >data-output.txt 2>err-output.tmp; type err-output.tmp >&2; del err-output.tmp
It follows that PowerShell is aware of
cmd.exe
's redirections and adjusts its behavior intentionally.(This is also evident from PowerShell producing colored output in the
cmd.exe
console while stripping the color codes when output is redirected to a file.)您可能想要这个:
您可能还会看到以下内容,但它假设您的 PowerShell 主机是控制台
窗口/设备,所以我认为它不太有用:
You probably want this:
You might also see the following, but it assumes your PowerShell host is a console
window/device, so I consider it less useful: