[英]Powershell with Git Command Error Handling - automatically abort on non-zero exit code from external program
[英]Don't throw PowerShell exception on writes to stderr from external command
当外部命令(例如 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 的退出状态为零,表示它已成功。 在 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 注册一个错误。 我可以只隐藏消息并手动检查退出状态,但我不想在显示时隐藏实际的错误消息。 此命令确实避免了异常:
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。 如何在不完全阻止 stderr 的情况下防止 PowerShell 脚本中的本机命令在写入 stderr 时抛出异常?
tl;博士
在PowerShell ISE中最简单的解决方法是以下(不需要在常规控制台或在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
有关其他解决方法,包括通过源流区分行的能力,请参阅此答案。
但是,您最好切换到 Visual Studio Code作为您的开发环境,这从根本上解决了问题 - 见下文。
两个旁白:
您看到的是非终止错误,而不是异常(虽然 .NET 异常是 PowerShell 错误处理的基础,但它们始终包含在[System.Management.Automation.ErrorRecord]
实例中,并且可能会或可能不会中止执行(终止与非-终止错误))。
try
/ catch
不捕获非终止错误,只捕获终止错误; 虽然您可以事先设置$ErrorActionPreference = 'Stop'
以将非终止错误提升为终止错误,但您的程序(在 ISE 中)的执行将在收到第一个stderr 行时中止。
如果您只PowerShell中使用的话,可以避免这个问题:
终端(控制台) ,包括即将推出的Windows 终端
带有PowerShell 扩展的Visual Studio Code ; 此跨平台编辑器 (IDE) 旨在取代过时的 Windows PowerShell ISE 。
这些环境的行为与您预期的一样:
笔记:
在远程处理和后台作业的上下文中,stderr 输出仍然发送到 PowerShell 的错误流。
将2>
与外部程序一起使用还存在其他与主机无关的问题。
有关所有问题的全面概述,请参阅此答案。
如何在不完全阻止 stderr 的情况下防止 PowerShell 脚本中的本机命令在写入 stderr 时引发异常?
您可以使用 Git 2.16+尝试我在“ PowerShell Capture Git Output ”中提到的选项
set GIT_REDIRECT_STDERR=2>&1
然后检查是否所有内容都写入标准输出。
我通常将所有输出重定向到同一个目的地:
Invoke-Command -ScriptBlock {get-module} *>&1
或者有时我把它扔到一个文件中:
$scriptblock = {
get-module
}
Invoke-Command -ScriptBlock $scriptblock *>&1 >> file.txt
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.