git 从外部命令写入stderr时不引发PowerShell异常

u4vypkhs  于 2022-12-21  发布在  Git
关注(0)|答案(2)|浏览(100)

当一个外部命令,比如git,写入stderr时,PowerShell会生成一个NativeCommandError异常。我希望看到输出和stdout一起正常运行,就像它在标准UNIX/Linux系统上的样子一样。这个脚本需要运行很多本机命令,如果可能的话,我希望解决方案不会给每个命令增加太多混乱和维护。
在Linux上,可以按如下方式检出分支:

$ git checkout devel
Branch 'devel' set up to track remote branch 'devel' from 'origin'.
Switched to a new branch 'devel'

微妙之处在于最后一行被写入了stderr,但是git的退出状态为0,表示它成功了,在PowerShell下,我得到了这个结果:

PS> git checkout devel
Branch 'devel' set up to track remote branch 'devel' from 'origin'.
git : Switched to a new branch 'devel'
At line:1 char:1
+ git checkout devel
+ ~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (Switched to a new branch 'devel':String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError

检查$LASTEXITSTATUS时,它显示为0,表示 checkout 成功。但是,由于git的行为是向stderr中写入特定的消息,它会触发PowerShell注册错误。我可以隐藏消息并手动检查退出状态,但我不想在显示错误消息时隐藏实际的错误消息。

PS> git checkout devel 2>$null
Branch 'devel' set up to track remote branch 'devel' from 'origin'.

这是StackOverflow上的其他答案所建议的,但不是我所需要的。我曾尝试将stderr重定向到stdout,希望PowerShell能看到stdout上的所有输出,而不会触发异常,但它仍然会:

git checkout devel 2>&1
Branch 'devel' set up to track remote branch 'devel' from 'origin'.
git : Switched to a new branch 'devel'
At line:1 char:1
+ git checkout devel 2>&1
+ ~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (Switched to a new branch 'devel':String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError

我也尝试过捕获异常,但是try.. catch块似乎没有阻止它:

PS> Try { git checkout devel 2>&1 } catch { echo "There was an error, ignore" }
Branch 'devel' set up to track remote branch 'devel' from 'origin'.
git : Switched to a new branch 'devel'
At line:1 char:7
+ Try { git checkout devel 2>&1 } catch { echo "There was an error, ign ...
+       ~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (Switched to a new branch 'devel':String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError

我只希望本机命令在退出状态为非零时导致失败,而不是在只写入stderr时。如何防止PowerShell脚本中的本机命令在写入stderr时引发异常,而不完全阻止stderr?

tvz2xvvm

tvz2xvvm1#

左,右
PowerShellISE最简单的解决方法如下(在常规控制台或Visual Studio代码中 * 不 * 需要):

# Redirect stderr (2) to the success stream (1).
# Doing so wraps stderr lines in [System.Management.Automation.ErrorRecord]
# instances; calling .ToString() on them returns them as normal text.
# CAVEAT: BE SURE THAT $ErrorActionPreference = 'Stop' is NOT IN EFFECT.
git checkout devel 2>&1 | % ToString

有关其他解决方法(包括通过源流区分线的能力),请参见this answer
然而,您最好切换到Visual Studio Code作为您的开发环境,这从根本上解决了这个问题-见下文。
两个旁白:

  • 您看到的是 * 非终止 * 错误,而不是异常(虽然. NET异常 * 支持 * PowerShell的错误处理,但它们总是 Package 在[System.Management.Automation.ErrorRecord]示例中,可能会也可能不会中止执行(终止与非终止错误))。
  • try/catch不捕获 * 非 * 终止错误,只捕获终止错误;虽然您可以预先设置$ErrorActionPreference = 'Stop'以将非终止错误升级为终止错误,但在接收到 * 第一个 * stderr行时,您的程序(在ISE中)的执行将被 * 中止 *。

如果您将PowerShell的使用限制在以下范围内,则可以*避免 * 此问题

这些环境的行为与您的预期一致:

  • 默认情况下,stderr(标准错误)输出将传递到显示器
  • stderr行与常规行一样打印。

注:

      • 在 * 远程处理 * 和 * 后台作业 * 的上下文中,stderr输出仍发送到PowerShell的错误流**。
  • 在将2>与外部程序一起使用时,还存在其他与主机无关的问题。

有关所有问题的全面概述,请参见this answer

b4lqfgs4

b4lqfgs42#

如何防止PowerShell脚本中的本机命令在写入stderr时抛出异常,而不完全阻塞stderr?
您可以尝试with Git 2.16+,我在“PowerShell Capture Git Output“中提到的选项

set GIT_REDIRECT_STDERR=2>&1

然后检查是否所有内容都写在stdout中。
zett42在注解中添加:
此处显示的命令用于批处理脚本。
要使用的实际PowerShell命令为:

$env:GIT_REDIRECT_STDERR = '2>&1'

相关问题