具有Git命令错误处理的Powershell-在外部程序的非零退出代码时自动中止 [英] Powershell with Git Command Error Handling - automatically abort on non-zero exit code from external program

查看:193
本文介绍了具有Git命令错误处理的Powershell-在外部程序的非零退出代码时自动中止的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用Git部署我的Web应用程序。因此,在Teamcity中,我准备了我的应用程序(编译,缩小JS和HTML,删除未使用的文件等),然后执行Powershell构建步骤:

  $ ErrorActionPreference =停止 
git init
git远程添加源'%env.gitFolder%'
git fetch
git reset --mixed origin / master
git add。
git commit -m'%build.number%'
git push origin master

但是如果抛出异常,脚本将继续执行(即使我设置 $ ErrorActionPreference = Stop ),并且构建也会成功。



我希望脚本在出现错误时停止运行,并且构建失败。



我试图放入将stderr输出的格式设置为:在构建步骤上为错误,并在以下情况下失败构建,如果:构建运行器记录错误消息,则构建失败,但是



我尝试在脚本中放入try-catch,但未将其放入陷阱。



有人有停止脚本并失败的错误提示吗?



对不起,我英语,我是法语... ^^

解决方案

$ ErrorActionPreference 变量不是不适用于调用外部实用程序 ([控制台]应用程序),例如 git


只有两种确定方法 外部实用程序的成功与失败



  • 通过检查自动 $ LASTEXITCODE 变量,PowerShell将其设置为外部实用程序报告的 **退出代码 **。

    按照惯例, 0 的值表示成功 ,而任何 非零值表示 >失败 。 (请注意,某些实用程序,例如 robocopy.exe ,也使用某些非零退出代码来传达非错误条件。)



  • 如果您对报告的特定退出代码不感兴趣,则可以检查 Boolean 自动变量 $? ,它表示退出代码 0 $ True $ c>, $ False 表示任何非零退出代码。



    • 警告:至少在PowerShell [Core] 7.0中, $?会在以下情况下错误地反映 $ false $ LASTEXITCODE 0 stderr重定向( 2> *> )用于命令发出stderr输出(其本身不一定表示失败) )-请参见此GitHub问题


    • >
    • 因此这是一个不错的选择它形成为仅查询 $ LASTEXITCODE 而不查询 $?来推断失败与成功的关系。






代理失败时,通常需要使用 Throw 关键字来生成脚本终止错误。 p>

不过,请注意,有一个待定RFC 建议将对外部程序的调用正确集成到PowerShell的错误处理机制中,以用于将来的版本。




显然,请检查 $每次外部实用程序调用之后,LASTEXITCODE / $?都很麻烦,因此,有一个包装函数可以简化此过程:


注意:虽然此功能有效,但试图补偿分解-至少在v7.0中将带有嵌入式双引号的参数传递给外部程序。要获得此补偿,可以使用 iee 函数noreferrer>本地模块 ,可通过 Install-Module Native 从PowerShell库中安装。

  function Invoke-Utility {
<#
。概要
调用外部实用程序,确保成功执行。

.DESCRIPTION
调用一个外部实用程序(程序),如果该实用程序通过非零退出代码的
方式指示失败,则抛出脚本终止错误。

*以直接执行命令的方式传递命令。
*请勿使用&如果可执行文件名称不是文字,则将其作为第一个参数。

.EXAMPLE
调用实用程序git push

如果退出代码
非零,则执行git push`并引发脚本终止错误。
#>
$ exe,$ argsForExe = $ Args
$ ErrorActionPreference =‘继续’#以防止2>触发终止错误的重定向。
试试{& $ exe $ argsForExe} catch {抛出}#仅在找不到$ exe时触发catch,从不为$ exe本身报告的错误
if($ LASTEXITCODE){抛出 $ exe表示失败(退出代码$ LASTEXITCODE;完整命令:$ Args)。 }
}

现在,您只需要在上添加调用实用程序传递给所有 git 调用,并且如果其中任何一个报告非零退出代码,则脚本将中止。


如果太冗长了,为您的函数定义一个别名: Set-Alias iu Invoke-Utility ,在这种情况下,您只需要在 iu之前加上

  iu git init 
iu git远程添加起点'%env.gitFolder%'
iu git fetch
#...


I use Git to deploy my web application. So in Teamcity I prepare my application (compilation, minify JS and HTML, delete unused files, etc...) and then I have a Powershell build step :

$ErrorActionPreference = "Stop"
git init
git remote add origin '%env.gitFolder%'
git fetch
git reset --mixed origin/master
git add .
git commit -m '%build.number%'
git push origin master

But if an exception throw, the script continue (even if I set $ErrorActionPreference = "Stop") and the build is successful.

I want the script to stop when there is an error, and the build to failed.

I tried to put Format stderr output as: error on the build step and Fail build if: an error message is logged by build runner, so the build failed, but the script continue, and so it's creating an stupid commit.

I try to put a try-catch in my script, but it doesn't enter in the catch...

Does anyone have an idea to stop the script and failed the build on error ?

Sorry for my English, I'm French... ^^

解决方案

The $ErrorActionPreference variable does not apply to calling external utilities ([console] applications) such as git.

There are only two ways to determine success vs. failure of an external utility:

  • By examining the automatic $LASTEXITCODE variable, which PowerShell sets to the **exit code reported by the external utility**.
    By convention, a value of 0 indicates success, whereas any nonzero value indicates failure. (Do note that some utilities, e.g., robocopy.exe, use certain nonzero exit codes to communicate non-error conditions too.)

  • If you're not interested in the specific exit code reported, you can examine the Boolean automatic variable $?, which reflects $True for exit code 0, and $False for any nonzero exit code.

    • Caveat: Up to at least PowerShell [Core] 7.0, $? can falsely reflect $false when $LASTEXITCODE is 0 and a stderr redirection (2> or *>) is used and the command emitted stderr output (which in itself doesn't necessarily indicate failure) - see this GitHub issue.

    • It is therefore a good habit to form to query only $LASTEXITCODE, not $? to infer failure vs. succcess.

Acting on a failure requires explicit action, typically by using the Throw keyword to generate a script-terminating error.

However, note that there is a pending RFC that proposes proper integration of calls to external programs into PowerShell's error-handling mechanisms for future versions.


Clearly, checking $LASTEXITCODE / $? after every external-utility call is cumbersome, so here's a wrapper function that facilitates this process:

Note: While this function works, it does not try to compensate for the broken-up-to-at-least-v7.0 passing of arguments with embedded double quotes to external programs. To get this compensation, you can use the iee function from the Native module, installable from the PowerShell Gallery via Install-Module Native.

function Invoke-Utility {
<#
.SYNOPSIS
Invokes an external utility, ensuring successful execution.

.DESCRIPTION
Invokes an external utility (program) and, if the utility indicates failure by 
way of a nonzero exit code, throws a script-terminating error.

* Pass the command the way you would execute the command directly.
* Do NOT use & as the first argument if the executable name is not a literal.

.EXAMPLE
Invoke-Utility git push

Executes `git push` and throws a script-terminating error if the exit code
is nonzero.
#>
  $exe, $argsForExe = $Args
  $ErrorActionPreference = 'Continue' # to prevent 2> redirections from triggering a terminating error.
  try { & $exe $argsForExe } catch { Throw } # catch is triggered ONLY if $exe can't be found, never for errors reported by $exe itself
  if ($LASTEXITCODE) { Throw "$exe indicated failure (exit code $LASTEXITCODE; full command: $Args)." }
}

Now you just need to prepend Invoke-Utility  to all your git calls, and if any of them reports a nonzero exit code, the script is aborted.

If that is too verbose, define an alias for your function: Set-Alias iu Invoke-Utility, in which case you only need to prepend iu :

iu git init
iu git remote add origin '%env.gitFolder%'
iu git fetch
# ...

这篇关于具有Git命令错误处理的Powershell-在外部程序的非零退出代码时自动中止的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆