在共享库中使用
env
对象时,env.HOME
值不会随 dockerized 阶段而变化。当 shell 步骤执行时,其 HOME
指向正确的值。
在下面的情况下,我期望
env.HOME == sh(script:'echo $HOME', returnStdout: true).trim()
并且它在 agent 阶段 实现,但不在 dockerized 阶段。
解决这个问题很简单(使用withEnv来设置,在shell命令中使用
~
或$HOME
从shell而不是groovy层拉回家)
我只是想知道背后的原因。
def info() {
println "Stage: ${env.STAGE_NAME}, env.HOME: ${env.HOME}
sh 'echo HOME=$HOME'
}
# Jenkinsfile
...
stages {
stage('agent') {
steps {
script { foo.info() }
}
}
stage('dockerized') {
agent {
docker {
image runnerImage
reuseNode true
}
}
steps {
script { foo.info() }
}
Stage: agent, HOME: /home/ec2-user
echo HOME=/home/ec2-user
HOME=/home/ec2-user
Stage: agent, HOME: /home/ec2-user
echo HOME=/home/jenkins
HOME=/home/jenkins
愚蠢的我,答案出现在一些失眠期间。 HOME 环境变量是由包含的操作系统本身设置的,因此 Jenkins 及其共享库无法知道它是什么。
/etc/passwd 和镜像 Dockerfile 中
USER
的设置决定了 HOME。 HOME 中的任何配置文件或 rc 文件都会添加额外的环境变量。
从库设计者的角度来看,限制此类损害的方法是:
sh "ls ${env.HOME}" // bad idea, the HOME may not match container's idea
sh 'ls $HOME' // better, resolution from shell not Gstring
sh "ls ~" // ~ auto resolves to $HOME within shell
-e ${HOME}:HOME
我还建议尽可能使用与代理操作系统结构一致的映像,但如果您的共享库被数百或数千个构建作业使用,您无法知道会出现这种情况,最好降低风险.