问题:
在将 Jenkinsfile 中声明的变量传递给sh
ssh 并在远程主机上执行的命令时,变量内容不会保留在远程主机上。
内置的 Jenkins 变量在本地和远程主机上都可以很好地保留。我定义的变量在本地可以正常工作,但不能在远程主机上转换。
虽然这个问题引用了 Docker,但这实际上是 100% 基于 Jenkins 管道的,因为它可以适用于任何有或没有 Docker 的示例。
背景:
我正在尝试根据当前构建标签动态创建图像名称并将该名称放入变量中。
然后我将该变量传递到sh
远程到 Docker 主机的步骤中,并使用定义的名称运行构建步骤。
Jenkinsfile 适用部分的片段...
// The below stage just echo's out some stuff into a file dockerimgname.jenkins.out
stage ('Construct Img name') {
sh '''echo ${BUILD_TAG} | awk '{print tolower($0)}' | sed 's/jenkins-//' > dockerimgname.jenkins.out'''
}
// This stage reads that file from previous stage and puts the value into variable.
// The variable is echo'd locally which works perfectly. Then ssh is called to execute command on remote host. That's where the variable value doesn't work.
stage ('Build Target Container') {
def jobBaseName = readFile 'dockerimgname.jenkins.out'
echo "${jobBaseName}"
sh 'ssh -i ~/ssh_keys/key.key user@somehost "cd /dockerdata/build/${BUILD_TAG} && docker build -t localrepo/${jobBaseName}:${BUILD_NUMBER} ."'
}
通常我会假设它没有变量,因为它是远程主机......但是奇怪的是${BUILD_NUMBER}
,${BUILD_TAG}
在远程主机上翻译和工作正常。为什么没有${jobBaseName}
??(它在远程主机上显示为空/null)。
由于不能保证您的各个阶段将在同一个执行程序节点上运行(除非您将阶段包装在同一个
node
块中),因此使用文件在阶段之间共享信息将是不可靠的。而是使用变量:顺便说一句,我还建议使用
sshAgent
Jenkins 的内置凭证存储来管理 SSH 密钥,而不是手动将-i
标志传递给 SSH。