Jenkins docker.image.inside()并行执行时变量取值错误如何解决
问题根因
这个问题是Groovy语言的闭包延迟绑定特性导致的,和Docker插件本身没有关系:for循环里定义的变量x是全局复用的同一个引用,所有闭包捕获的都是这个引用,等到并行任务实际执行的时候,循环已经跑完了,x的值已经更新为数组最后一个元素2,所以所有任务输出都是2。
额外优化提示:你原有代码里闭包内复用了外层的
image变量名做赋值,并行场景下会出现全局变量覆盖问题,修正方案里也同步做了调整,单独定义局部变量存储拉取到的镜像对象。
解决方案
方案1:替换for循环为each迭代(最简便)
Groovy的each方法每次迭代都会生成独立的变量副本,闭包会捕获对应迭代的独立变量,不会出现引用复用问题,修正后代码如下:
node { x_array = [1,2] x_map = [:] image = "centos:latest" x_array.each { x -> x_map[x] = { def dockerImage = docker.image(image) dockerImage.pull() dockerImage.inside("-t") { sh "echo $x" } } } parallel x_map }
方案2:for循环内声明局部变量缓存当前值
如果要保留for循环写法,可以在循环内部用def声明一个局部变量,把当前x的值赋值给这个局部变量,闭包捕获局部变量即可,每次循环的局部变量是独立的,修正后代码如下:
node { x_array = [1,2] x_map = [:] image = "centos:latest" for (x in x_array) { def currentX = x // 声明局部变量缓存当前迭代值 x_map[x] = { def dockerImage = docker.image(image) dockerImage.pull() dockerImage.inside("-t") { sh "echo $currentX" } } } parallel x_map }
内容的提问来源于stack exchange,提问作者Rice
相关产品推荐
相关产品推荐

