git - 从外部命令向stderr写入时不要抛出PowerShell异常

标签 git powershell error-handling

当外部命令(例如git)写入stderr时,PowerShell会生成NativeCommandError异常。我希望看到输出和stdout正常,类似于标准UNIX/Linux系统上的输出。该脚本需要运行许多 native 命令,我希望有一种解决方案,该解决方案在可能的情况下不会给每个命令增加过多的困惑和维护。

在Linux上,可以按以下方式 check out 分支:

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

最微妙的部分是,无论出于何种原因,最后一行都写到了stderr上。但是,git的退出状态为零,表明成功。在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,它显示为零,指示结帐成功。但是,由于git的行为是向stderr写入某些消息,因此它会触发PowerShell注册错误。我可以只 stash 消息并手动检查退出状态,但是我不想在显示错误消息时 stash 它们。此命令可避免出现以下异常:
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 异常,但是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

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

最佳答案

tl;博士

以下是PowerShell ISE 的最简单的解决方法(在常规控制台或Visual Studio Code中不需要):

# 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的错误处理的基础,但它们始终包装在[System.Management.Automation.ErrorRecord]实例中,并且可能会(也可能不会)中止执行(终止与非终止错误)。
  • try/catch不会捕获非终止错误,只会终止错误。尽管您可以预先设置$ErrorActionPreference = 'Stop'来将非终止错误升级为终止错误,但是在接收到第一条stderr行时,将终止程序(在ISE中)的执行。


  • 如果将PowerShell的使用范围限制为:,您可以避免此问题
  • 一个终端(控制台),包括即将推出的Windows Terminal
  • Visual Studio CodePowerShell extension ;该跨平台编辑器(IDE)旨在取代obsolescent Windows PowerShell ISE

  • 这些环境的行为符合您的预期:
  • stderr(标准错误)输出默认传递给显示器
  • stderr行的打印与常规行一样。

  • 笔记:
  • 在远程作业和后台作业的上下文中,stderr输出仍将发送到PowerShell的错误流
  • 通过将2> 与外部程序一起使用,还存在其他,独立于主机的问题。

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

    关于git - 从外部命令向stderr写入时不要抛出PowerShell异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59366288/

    相关文章:

    git - 无法从 Assembla 克隆

    powershell - 如何在powershell中[int]添加[string]正则表达式替换?

    c# - 长时间运行的应用程序,如何处理错误?

    mysql - 复制唯一字段时返回错误消息

    php - 在PHP中为函数返回逻辑错误的最佳实践是什么

    git - 如何从git分支中删除文件

    git - 如何在 GitHub 上获取其他人的分支上的分支?

    php - 有 git 问题警告

    regex - PowerShell -match 与 -simplematch

    powershell - "OutOfMemoryException"对 60Gb 文件使用压缩归档时