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

Jenkins流水线Shell变量复用报错,如何正确转义编写?

Jenkins流水线更新ECS任务定义报错解决

问题场景

在Jenkins流水线中编写了以下阶段代码,用于更新ECS任务定义与服务:

stage('Update ECS Task Definition & Service') {
    steps {
        dir('foo') {
            sh """
                TASK_DEFINITION=\$(aws ecs describe-task-definition --task-definition "${env.TASK_NAME}" --region "${env.AWS_REGION}")
                NEW_TASK_DEFINITION=\$(echo \${TASK_DEFINITION} | jq '.taskDefinition | del(.taskDefinitionArn) | del(.revision) | del(.status) | del(.requiresAttributes) | del(.compatibilities) | del(.registeredAt) | del(.registeredBy)')
                NEW_REVISION=\$(aws ecs register-task-definition --region "${env.AWS_REGION}" --cli-input-json "${NEW_TASK_DEFINITION}")
                NEW_REVISION_DATA=\$(echo \${NEW_REVISION} | jq '.taskDefinition.revision')
                echo "New Revision for ${env.TASK_NAME} is: \${NEW_REVISION_DATA}"
            """
        }
    }
}

报错信息

执行后抛出如下异常:

groovy.lang.MissingPropertyException: No such property: NEW_TASK_DEFINITION for class: groovy.lang.Binding

问题原因

核心问题是Groovy字符串插值规则冲突:
Jenkins流水线中使用三重双引号"""包裹shell脚本时,Groovy会自动解析所有${xxx}格式的内容,将其视为Groovy环境中的变量。而脚本里的${NEW_TASK_DEFINITION}、${NEW_REVISION}等是shell脚本内部的变量,并非Groovy变量,因此Groovy会报错找不到对应的属性。

你之前仅转义了$(...)中的$,但未转义shell变量引用的${...}中的$,导致Groovy错误解析这些内容。

修正后的代码

给所有shell内部的变量引用的$添加转义符\,让Groovy将其当作普通字符传递给shell执行,同时保留Groovy环境变量${env.TASK_NAME}、${env.AWS_REGION}的直接引用:

stage('Update ECS Task Definition & Service') {
    steps {
        dir('foo') {
            sh """
                TASK_DEFINITION=\$(aws ecs describe-task-definition --task-definition "${env.TASK_NAME}" --region "${env.AWS_REGION}")
                NEW_TASK_DEFINITION=\$(echo \${TASK_DEFINITION} | jq '.taskDefinition | del(.taskDefinitionArn) | del(.revision) | del(.status) | del(.requiresAttributes) | del(.compatibilities) | del(.registeredAt) | del(.registeredBy)')
                NEW_REVISION=\$(aws ecs register-task-definition --region "${env.AWS_REGION}" --cli-input-json "\${NEW_TASK_DEFINITION}")
                NEW_REVISION_DATA=\$(echo \${NEW_REVISION} | jq '.taskDefinition.revision')
                echo "New Revision for ${env.TASK_NAME} is: \${NEW_REVISION_DATA}"
            """
        }
    }
}

关键修改点

  • 将--cli-input-json "${NEW_TASK_DEFINITION}"改为--cli-input-json "\${NEW_TASK_DEFINITION}",给shell变量的$添加转义
  • 确保所有shell内部的变量引用(如\${TASK_DEFINITION}、\${NEW_REVISION_DATA})都保留\转义,避免Groovy错误解析

更简洁的写法(可选)

如果不想处理复杂的转义,可以改用单引号包裹shell脚本,此时Groovy不会解析内部的${xxx},但需要手动将Groovy环境变量传递到shell中:

stage('Update ECS Task Definition & Service') {
    steps {
        dir('foo') {
            sh '''
                TASK_DEFINITION=$(aws ecs describe-task-definition --task-definition "'"${env.TASK_NAME}"'" --region "'"${env.AWS_REGION}"'")
                NEW_TASK_DEFINITION=$(echo ${TASK_DEFINITION} | jq '.taskDefinition | del(.taskDefinitionArn) | del(.revision) | del(.status) | del(.requiresAttributes) | del(.compatibilities) | del(.registeredAt) | del(.registeredBy)')
                NEW_REVISION=$(aws ecs register-task-definition --region "'"${env.AWS_REGION}"'" --cli-input-json "${NEW_TASK_DEFINITION}")
                NEW_REVISION_DATA=$(echo ${NEW_REVISION} | jq '.taskDefinition.revision')
                echo "New Revision for "'"${env.TASK_NAME}"'" is: ${NEW_REVISION_DATA}"
            '''
        }
    }
}

这种写法通过'"${env.XXX}"'的方式,将Groovy变量插入到单引号包裹的shell脚本中,避免了转义冲突,代码可读性更强。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 09:10:34