git - 带有 Git 命令错误处理的 Powershell - 自动中止外部程序的非零退出代码

标签 git powershell error-handling teamcity exit-code

我使用 Git 来部署我的 Web 应用程序。所以在 Teamcity 中,我准备了我的应用程序(编译、缩小 JS 和 HTML、删除未使用的文件等...),然后我有一个 Powershell 构建步骤:

$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

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

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

我试着把 Format stderr output as: error在构建步骤和 Fail build if: an error message is logged by build runner ,所以构建失败,但脚本继续,所以它创建了一个愚蠢的提交。

我尝试在我的脚本中放入一个 try-catch,但它没有进入 catch ......

有没有人有停止脚本的想法并因错误而导致构建失败?

对不起我的英语,我是法国人...^^

最佳答案

$ErrorActionPreference变量不适用于调用外部实用程序 ([控制台] 应用程序)如 git .
只有确定外部实用程序成功与失败的两种方法 :

  • 通过检查 自动 $LASTEXITCODE变量 ,PowerShell 将其设置为 **外部实用程序报告的退出代码**。
    按照惯例,值为 0表示成功 , 而任何 非零值表示失败 . (请注意,某些实用程序,例如 robocopy.exe ,也使用某些非零退出代码来传达非错误条件。)
  • 如果您对报告的特定退出代码不感兴趣,可以查看 bool 型自动变量$? ,反射(reflect)了 $True退出代码 0 , 和 $False对于任何非零退出代码。
  • 注意事项 :从 PowerShell (Core) 7.1 开始,有两个 错误 ;这两个都是通过 PSNotApplyErrorActionToStderr 暂时修复的7.2 预览版中的实验性功能 (!)(默认情况下,所有实验性功能在新安装的预览版中都处于打开状态)——我们希望这些修复能够进入 7.2:
  • $?可以虚假反射(reflect)$false$LASTEXITCODE0并且使用 stderr 重定向( 2>*> )并且命令发出 stderr 输出(这本身并不一定表示失败) - 参见 GitHub issue #10512 .
  • 因此形成只查询$LASTEXITCODE 是一个好习惯。 ,不是 $?推断失败与成功。

  • $ErrorActionPreference设置为 'Stop'而你碰巧使用了 2>*>使用外部程序,该程序产生实际的 stderr 输出,$ErrorActionPreference意外地适用并导致脚本终止错误(无论外部程序是否通过非零退出代码表示实际失败) - 参见 GitHub issue #4002



  • 对故障采取行动需要明确的行动 ,通常使用 Throw关键字以生成脚本终止错误。
    但是,请注意有一个 pending RFC这建议将外部程序调用正确集成到 PowerShell future 版本的错误处理机制中。

    显然,检查 $LASTEXITCODE/$?在每次外部实用程序调用之后都很麻烦,所以这里有一个 包装函数 促进这一过程:
    备注 :虽然此功能有效,但它不会尝试补偿 broken-up-to-at-least-v7.1 passing of arguments with embedded double quotes to external programs .要获得此补偿,您可以使用 iee来自 Native module 的函数 ,可通过 Install-Module Native 从 PowerShell 库安装.
    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
      # Workaround: Prevents 2> redirections applied to calls to this function
      #             from accidentally triggering a terminating error.
      #             See bug report at https://github.com/PowerShell/PowerShell/issues/4002
      $ErrorActionPreference = 'Continue'
      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)." }
    }
    
    现在你只需要添加 Invoke-Utility 给你所有的 git调用,如果其中任何一个报告非零退出代码,则脚本将中止。
    如果这太冗长,请为您的函数定义一个别名:Set-Alias iu Invoke-Utility ,在这种情况下,您只需要添加 iu  :
    iu git init
    iu git remote add origin '%env.gitFolder%'
    iu git fetch
    # ...
    

    关于git - 带有 Git 命令错误处理的 Powershell - 自动中止外部程序的非零退出代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48864988/

    相关文章:

    AZ 存储 Blob 上的 Azure CLI IF 存在结果

    sql - SQL ORA-00933命令未正确结束

    android - 从 Android Studio 自动提交并推送到 GitHub

    git - Jenkins 构建最新提交,而不是 GitHub 提交后 Hook 指定的提交

    powershell - Ping 网络打印机列表

    linux - 如何在 shell 脚本中获取最后一个 Bash shell 命令的成功状态?

    php - 在页脚标记内关闭MySQL连接

    java - 在 git 中移动文件时什么时候提交? (Jgit)

    git - 从CloudBuild访问GitHub存储库

    POWERSHELL:$Image.DrawString 居中字符串,左右填充