Jenkins流水线双引号执行curl上传Nexus失败,需实现脚本变量插值
问题根因
你使用双引号包裹sh命令时,变量插值会在Jenkins Groovy解析阶段提前完成:withCredentials注入的XYZ(用户名)、ABCD(密码)是Jenkins生命周期内的环境变量,若密码包含$、空格、&、!等shell特殊字符,Groovy直接插值后传入shell执行时,会被shell解析为语法片段,最终触发找不到文件/命令的报错。
而单引号包裹时Groovy不会做任何插值操作,$XYZ:$ABCD会直接传递给shell层读取当前进程的环境变量,自然可以正常运行,但缺点是无法插入Groovy层面定义的自定义参数。
解决方案
既支持Groovy自定义参数插值、又避免凭证特殊字符解析问题的方案有两种:
方案1:转义凭证变量的$符号,保留双引号插值
只需要把凭证相关变量的$用反斜杠转义,Groovy就不会提前解析这部分变量,而是交给shell层读取环境变量;自定义参数正常用${}做Groovy插值即可,示例如下:
// 示例:Groovy层面定义的自定义参数 def customVersion = "v1.0.${BUILD_ID}" def targetFile = "xyz-${customVersion}.tar.gz" withCredentials([usernamePassword(credentialsId: 'xxxxxxxxxxx', passwordVariable: 'ABCD', usernameVariable: 'XYZ')]) { dir("build") { // 仅凭证变量的$加反斜杠转义,自定义参数直接用${}插值 sh "curl -u \$XYZ:\$ABCD --upload-file ${targetFile} https://mnpqr/repository/abc/${BRANCH_DIR}/${targetFile}" } }
方案2:使用多行字符串脚本,统一在shell层处理参数
如果需要插入的自定义参数较多,也可以直接用三个双引号包裹多行shell脚本,所有变量(包括自定义参数、凭证变量)都在shell层读取,避免跨层插值混乱:
withCredentials([usernamePassword(credentialsId: 'xxxxxxxxxxx', passwordVariable: 'ABCD', usernameVariable: 'XYZ')]) { dir("build") { sh """ # shell层面定义自定义参数,也可直接读取Jenkins内置环境变量 CUSTOM_VERSION="v1.0.${BUILD_ID}" TARGET_FILE="xyz-\${CUSTOM_VERSION}.tar.gz" TARGET_URL="https://mnpqr/repository/abc/\${BRANCH_DIR}/\${TARGET_FILE}" # 执行上传,直接读取shell环境变量 curl -u \$XYZ:\$ABCD --upload-file \${TARGET_FILE} \${TARGET_URL} """ } }
注意事项
如果你的自定义参数可能包含空格、特殊符号,在shell中引用时需要额外加双引号包裹,避免shell误拆分参数,例如:
curl -u \$XYZ:\$ABCD --upload-file "${TARGET_FILE}" "${TARGET_URL}"
内容的提问来源于stack exchange,提问作者JackSparow
相关产品推荐
相关产品推荐

