【问题标题】:Powershell exception stopping execution even with try/catch即使使用 try/catch,Powershell 异常也会停止执行
【发布时间】:2021-04-20 02:31:45
【问题描述】:

我们有一个在我们的管道中执行的 powershell 脚本,它有一些命令,如果发生任何错误,它们不应停止。我尝试将脚本块放在 try/catch 中,但管道仍然因错误而停止:

这是代码:

    try {   
        az network dns record-set txt add-record `
            -g $ResourceGroup `
            -n "asuid.$DomainName" `
            -v $VerificationId `
            -z $Zone
    
        $record = az network dns record-set cname create `
            -g $ResourceGroup `
            -n $DomainName `
            -z $Zone `
            -o json | ConvertFrom-Json
    
        az network dns record-set cname set-record `
            -g $ResourceGroup `
            -n $record.name `
            -c $Alias `
            -z $Zone
    }
    catch {
        Write-Warning "Creating a DNS record was not possible. Consider creating it by hand or review the error:"
        Write-Warning $_
    }

我知道一些解决方法,比如告诉管道在出错时继续运行,或者只是使用-ErrorAction Continue 执行 cmdLet,但对我来说,为什么这不能像我一样工作是没有任何意义的。至少对于来自 C# 和其他语言的我来说,如果您不想重新抛出异常,那将是默认行为。

我错过了什么概念?

编辑 1

这是 yaml 中任务失败的部分:

  - task: AzureCLI@2
    name: create_dns_record
    displayName: "Creates a DNS record for CNAME and TXT on DNS Zone"
    inputs:
      azureSubscription: 'some-azure-subscription'
      scriptType: 'pscore'
      scriptLocation: 'inlineScript'
      inlineScript: |
        . $(System.DefaultWorkingDirectory)/cd/NewDNSRecordSet.ps1
          
        New-DNSRecordSet `
            -ResourceGroup 'rg_zones' `
            -DomainName '$(domain_name)' `
            -Zone '$(dns_zone)' `
            -VerificationId '$(verificationId)' `
            -Alias '$(defaultHostName)' # verificationId and defaultHostName as output from the task CreateInfrastructure.ps1

这是管道的输出:

Creating DNS Recordset for 'mytest.dev' zone.
Adding txt record: asuid.mytest
ResourceNotFoundError: Resource group 'rg_zones' could not be found.
Creating CNAME record: mytest
ResourceNotFoundError: Resource group 'rg_zones' could not be found.
WARNING: Creating a DNS record was not possible.
##[error]Script failed with exit code: 1

【问题讨论】:

  • 这 3 个命令中的哪个命令失败?是第一个吗?如果是第一个,其他两个会被处决吗?
  • 通常az 命令是幂等的。唯一失败的是最后一个,因为$recordnull。这是一个空引用异常。我添加了if ($record)..,但管道仍然因错误而停止。
  • 这是因为 $LASTEXITCODE 自动变量。您还应该设置$ErrorActionPreference = 'Stop'
  • 但我不想停止,管道应该继续...$ErrorActionPreference = 'Stop' 会让我的管道停止
  • 如果您的 $ErrorActionPreference 设置为 Continue/SilentlyContinue,一个会引发错误的命令反而运行良好,这意味着如果您的 try 块中有某些内容可能 throw,它永远不会进入 catch 块。从我在您的帖子中看到的情况来看,这正是您所不期望的。首先在本地测试您的脚本。

标签: powershell azure-pipelines


【解决方案1】:

所以为了测试我的假设,我在我的 PowerShell 中本地编写了这段代码:

$ErrorActionPreference = 'Stop'

try {
    & 'az' @('group', 'show', '--name', 'foo')

    Write-Host "in try: $LASTEXITCODE"
}
catch {
    $_
    Write-Host "in catch: $LASTEXITCODE"
}

我得到了输出:

Resource group 'foo' could not be found.
in try: 3

所以az 命令失败,退出代码非零,但它没有抛出错误。 try 块执行良好,我的脚本结束。

如果您在管道中运行它,非零退出代码将导致管道失败。我的建议是创建某种辅助方法来在 PowerShell 中执行 az CLI 命令,验证 $LASTEXITCODE 并自己抛出一个错误,以便稍后捕获它。

【讨论】:

  • 这很好。我认为错误在于 Azure DevOps 中的 AzureCLI 任务,所以我不明白 AzureCLI 任务在幕后做什么。 try catch 应该可以完成这项工作。我将使用 yaml 部分更新我的线程。
  • 好东西。我最终确实写了一个助手
猜你喜欢
  • 2017-01-30
  • 2014-08-28
  • 2022-11-30
  • 1970-01-01
  • 2021-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-07
相关资源
最近更新 更多