Jenkins声明式Pipeline并行执行时仅调用列表最后一项的问题
解决Jenkins声明式Pipeline并行遍历列表时始终调用最后一项的问题
这是Groovy闭包延迟绑定导致的经典问题,我之前也踩过这个坑!
你代码里的for(i in my_list)循环在创建闭包时,并没有把当前迭代的i值“固定”下来。Groovy的闭包会在执行的时候才去读取变量i的当前值,而不是定义闭包时就捕获它。等你执行parallel shouter的时候,循环已经跑完了,i已经指向列表的最后一项server-3,所以所有并行任务都会复用这个值。
修正方案
有两种简单的办法可以解决这个问题:
方法1:用局部变量捕获当前迭代值
在循环内部定义一个局部变量,把当前的i赋值给它,这样每个闭包都会引用这个独立的局部变量,而不是共享的循环变量i:
pipeline { agent any stages { stage('set servers') { steps { script { my_list = ['server1','server-2','server-3'] } } } stage('Execute then') { parallel { stage('shouter') { steps { script { shouter = [:] for(i in my_list) { // 用局部变量固定当前迭代的服务器名称 def currentServer = i shouter["${currentServer}"] = { echo "standupandshout.sh ${currentServer}" } } parallel shouter } } } } } } }
方法2:使用each遍历列表
Groovy的each方法会为每个元素创建独立的上下文,自动捕获当前元素的值,彻底避免共享变量的问题:
pipeline { agent any stages { stage('set servers') { steps { script { my_list = ['server1','server-2','server-3'] } } } stage('Execute then') { parallel { stage('shouter') { steps { script { shouter = [:] my_list.each { server -> shouter["${server}"] = { echo "standupandshout.sh ${server}" } } parallel shouter } } } } } } }
效果验证
修改后重新运行Pipeline,每个并行分支都会正确输出对应的服务器名称,比如server1分支会打印standupandshout.sh server1,再也不会全部复用最后一个值了。
内容的提问来源于stack exchange,提问作者thclpr
相关产品推荐
相关产品推荐

