You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure Function PowerShell实现ACR同步时Try Catch重试逻辑失效求助

问题排查与修复方案

核心问题根因

  • 外部命令异常捕获失效:az 是Azure CLI的外部可执行程序,不属于PowerShell原生cmdlet,默认情况下它的执行失败只会设置$LASTEXITCODE退出码,不会抛出PowerShell异常,所以就算az acr import执行失败,也永远不会进入你写的catch代码块,重试逻辑完全不会触发。
  • 错误判断逻辑不准确:你通过全局$error变量判断是否执行成功,但$error会记录所有历史错误(包括az login产生的警告信息、之前执行的其他命令错误),很容易出现误判;且你设置的$global:erroractionpreference = 1可读性差,也不会作用于外部命令的错误捕获。
  • 循环与退出逻辑异常:脚本中执行成功后直接调用Exit,在Azure Function的PowerShell运行环境中会直接终止脚本执行,可能导致后续HTTP响应没有正确输出给触发器。

修复后的完整代码

using namespace System.Net
param($Request, $TriggerMetadata)

# 明确设置错误处理偏好,对PowerShell cmdlet生效
$ErrorActionPreference = 'Stop'
# 配置最多重试3次,加上首次执行总共有4次运行机会
$maxRetryCount = 3
$counter = 0
$syncSuccess = $false

# 登录逻辑移到循环外,无需每次重试重复登录
az login --service-principal --username $env:APP_ID --password $env:PASSWORD --tenant $env:TENANT_ID | Out-Null

Write-Host "ACR to ACR sync triggered"
$repo = $Request.Body.target.repository | Out-String
$repo = $repo.Trim() # 直接去除首尾空白字符,比单独替换换行兼容性更强
$aztag  = $Request.Body.target.tag | Out-String
$aztag = $aztag.Trim()
$imageString = "${repo}:${aztag}"
Write-Host "待同步镜像: $imageString"

do {
    try {
        Write-Host "开始执行同步,当前尝试次数: $($counter + 1)"
        az acr import --name $env:acr_name --source "$env:promoted_acr_name.azurecr.io/${imageString}" --image "${imageString}" --username $env:PromotedAPPID --password $env:PromotedPassword --force
        # 检查az命令退出码,0代表执行成功
        if ($LASTEXITCODE -eq 0) {
            $syncSuccess = $true
            break
        }
        throw "az acr import执行失败,退出码: $LASTEXITCODE"
    }
    catch {
        $ErrorMessage = $_.Exception.Message
        Write-Output "同步失败,错误信息: $ErrorMessage"
        $counter += 1
        if ($counter -le $maxRetryCount) {
            Write-Host "等待120秒后开始第 $counter 次重试"
            Start-Sleep -Seconds 120
        }
    }
} while ($counter -le $maxRetryCount)

if (-not $syncSuccess) {
    Write-Host "累计重试$maxRetryCount次后同步仍然失败"
    $StatusCode = [HttpStatusCode]::BadRequest
    $responseBody = "Sync failed after $maxRetryCount retries"
}
else {
    Write-Host "ACR镜像同步成功"
    $StatusCode = [HttpStatusCode]::OK
    $responseBody = "Sync succeeded"
}

# 向HTTP触发器返回响应,Azure Function PowerShell环境必须添加该逻辑才会正确返回响应
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
    StatusCode = $StatusCode
    Body = $responseBody
})

修复说明

  • 调整错误捕获逻辑:通过判断外部命令az的退出码$LASTEXITCODE识别执行失败,解决原代码catch块永远不触发的问题
  • 优化执行流程:将登录、镜像参数解析逻辑移到循环外,避免每次重试执行冗余操作,用Trim()替代换行替换兼容性更好
  • 新增明确的同步状态标记$syncSuccess,替代原逻辑中不可靠的全局$error变量判断
  • 补充Azure Function必需的HTTP响应输出逻辑,修复原代码直接Exit导致无法正确返回响应的问题
  • 重试次数可通过$maxRetryCount变量灵活配置,默认3次重试符合需求

内容的提问来源于stack exchange,提问作者hars34

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 07:15:03