如何禁止 PowerShell 中的标准错误输出?

How do I suppress standard error output in PowerShell?

提问人:sbi 提问时间:8/15/2012 最后编辑:sbi 更新时间:9/5/2022 访问量:55716

问:

在自动执行某些SVN任务的PowerShell脚本中,我具有以下功能:

function SvnUrlExists($url)
{
  svn info $url | out-null 2>&1
  return $?
}

由于这显式测试了某些SVN存储库URL是否存在,因此我对任何错误输出都不感兴趣。但是,尽管我在 PowerShell 中发现了有关重定向的所有内容,但建议将其重定向到 ,这仍然会输出错误消息stderr2>&1stdout

svn: warning: W170000: URL 'blahblah' non-existent in revision 26762
svn: E200009: Could not display info for all targets because some targets don't exist

不幸的是,这严重扰乱了我的脚本输出。

我做错了什么,我应该如何抑制这个错误输出?

svn powershell io-重定向

评论


答:

34赞 sbi 8/15/2012 #1

以防万一其他人在谷歌上搜索与我类似的术语:

在我用额头敲了几个小时之后,当然,我在这里发布问题后的几分钟内就找到了解决方案:

svn info $url 2>&1 | out-null

这就像一个魅力。

评论

0赞 Nick 8/15/2012
此外,如果您有更大的命令,则可以将其包装起来以获得相同的效果。例如:) |out-null'。当命令很长时,我会这样做,或者我需要在脚本中将其分成几行。$() | out-null$( svn info $url 2>&
0赞 sbi 8/16/2012
@Nick:啊,谢谢。但是,难道不是必须的吗?(请注意 .$( svn info $url ) 2>&1 | out-null2>&1
0赞 Nick 8/16/2012
哦,哇,我完全误读了你的帖子。是的,应该是.这取决于您希望对 进行错误检查的位置。我不能说没有测试它,但我认为它是在里面还是在外面都无关紧要。就像我说的,你实际上可以完全关闭,没有测试,我不能确定。$(svn info $url) | out-null2>&1)2>&1
0赞 cmcginty 4/24/2014
它有效,但如果在脚本中使用它,则会导致错误停止脚本。这可能不是预期的副作用。
1赞 thecoshman 2/19/2019
我遇到了这个问题,因为我有一个在通过 PowerShell 运行时无法保持安静的问题......我非常接近让 PS 调用“git bash”来处理 git 的东西。至少我可以相信 bash 会让东西静音。git commit
8赞 Zombo 6/21/2014 #2

也可以这样做:

svn info $url *> $null

请参阅在 PowerShell 中禁止显示控制台输出

about_Redirection

评论

1赞 honzakuzel1989 4/5/2016
或者 svn info $url 2> $null 仅用于 stderr。
5赞 David Bertrand 1/15/2016 #3

投票的答案为我生成了一个错误。解决方案最终如下:

cmd /c "MyProgram MyArguments 2>&1" | Out-Null

评论

3赞 Rafał Kłys 10/10/2017
将 stderr 重定向到 stdout 仍会生成错误并停止脚本执行,前提是 $ErrorActionPreference = 'Stop'。但是,如果您不将 stderr 重定向到 stdout,则不会发生错误。奇怪!
0赞 mklement0 10/10/2017
@Rafa łKłys:确实很奇怪;这是一个错误:请参阅 github.com/PowerShell/PowerShell/issues/4002
0赞 Carl Walsh 11/7/2020
对于任何跟踪此内容的人来说,这都被欺骗 github.com/PowerShell/PowerShell/issues/3996 并且 v7.1.0 版本(仍处于预览阶段)中将有一个修复程序,可能隐藏在标志后面PSNotApplyErrorActionToStderr
43赞 Daniel 7/28/2016 #4

如果只想抑制标准误差,请使用:

svn info $url 2>$null
5赞 mklement0 9/11/2019 #5

tl;博士

function SvnUrlExists($url)
{

  # Suppress all output streams (external stdout and stderr in this case)
  # To suppress stderr output only, use 2>$null
  svn info $url *>$null 

  # For predictable results with external programs, 
  # infer success from the *process exit code*, not from the automatic $? variable.
  # See https://github.com/PowerShell/PowerShell/issues/10512
  $LASTEXITCODE -eq 0
}

自己的答案有效地解决了重定向问题

Steven Penny 的回答建议,即抑制所有输出流作为一种方便的替代方案 - 它消除了对 的需求,我通常建议将其替换为 - 请参阅此答案*>$nullOut-Null$null = ...

但是,您问题中的代码还有另一个问题

虽然它可能适用于您的特定命令,但不幸的是,$?并不是外部程序是否成功的可靠指标 - 请改用$LASTEXITCODE -eq 0,因为 - 由于 PowerShell Core 7.0.0-preview.3 的错误,在 GitHub 上报告 此处 - 最终可能会反映,即使 是(明确表示成功)。$?$false$LASTEXITCODE0

  • 更新:如果 v7.2 之前的实验性功能成为官方功能,这个问题将消失 - 有关更多信息,请参阅此答案PSNotApplyErrorActionToStderr

至于你在问题中尝试了什么

svn info $url | out-null 2>&1  # WRONG
  • 只有成功输出才会发送到管道(外部程序的 stdout 输出将发送到 PowerShell 的成功输出)。

  • 重定向(例如)作用于管道中的单个命令,而不是整个管道。2>&1

  • 因此,如果产生 stderr 输出,它会直接打印到主机(控制台)上 - 永远不会看到它。svn info $urlOut-Null

评论

2赞 Matt Mills 2/25/2020
“像 2>&1 这样的重定向作用于管道中的单个命令,而不是整个管道。” - 这就是解决我遇到的问题的原因。
0赞 adamency 9/5/2022 #6

需要注意的重要一点是,某些 Powershell cmdlet 在这些方法中无法正确运行。这样的例子是,无论你使用什么技巧,它都会在失败时输出错误:Get-ADUser

PS C:\Temp\2022-09-05T08-28-46_oexvijzd.tfq> Get-ADUser -Identity "CN=administrator,DC=acme,DC=internal" 2>&1 | Out-Null
Get-ADUser : Directory object not found
At line:1 char:1
+ Get-ADUser -Identity "CN=administrator,DC=acme,DC=internal" 2>&1 | Ou ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (CN=administrator,DC=acme,DC=internal:ADUser) [Get-ADUser], ADIdentityNotFoundException
    + FullyQualifiedErrorId : ActiveDirectoryCmdlet:Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException,Microsoft.ActiveDirectory.Management.Commands.GetADUser
PS C:\Temp\2022-09-05T08-28-46_oexvijzd.tfq> Get-ADUser -Identity "CN=administrator,DC=acme,DC=internal" *>$null
Get-ADUser : Directory object not found
At line:1 char:1
+ Get-ADUser -Identity "CN=administrator,DC=acme,DC=internal" *>$null
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (CN=administrator,DC=acme,DC=internal:ADUser) [Get-ADUser], ADIdentityNotFoundException
    + FullyQualifiedErrorId : ActiveDirectoryCmdlet:Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException,Microsoft.ActiveDirectory.Management.Commands.GetADUser
PS C:\Temp\2022-09-05T08-28-46_oexvijzd.tfq> Get-ADUser -Identity "CN=administrator,DC=acme,DC=internal" *>$null | Out-Null *>$null
Get-ADUser : Directory object not found
At line:1 char:1
+ Get-ADUser -Identity "CN=administrator,DC=acme,DC=internal" *>$null | ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (CN=administrator,DC=acme,DC=internal:ADUser) [Get-ADUser], ADIdentityNotFoundException
    + FullyQualifiedErrorId : ActiveDirectoryCmdlet:Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException,Microsoft.ActiveDirectory.Management.Commands.GetADUser

在这些情况下,您将不得不创建/阻止,或寻找其他替代方案(例如,检查AD对象是否存在;如何避免丑陋的错误消息?trycatch

希望这能为某人省去一些无用的挠头。