You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jenkins流水线调用类返回闭包时执行shell命令无限阻塞求助

解决Jenkins流水线中闭包执行shell命令无限阻塞的问题

我之前也碰到过一模一样的问题,核心原因是你用@NonCPS注解包裹了返回闭包的buildDriver方法,这和Jenkins流水线的CPS执行机制直接冲突了。

问题根源

Jenkins流水线依赖**CPS(续体传递风格)**来管理执行流程:它需要把所有流水线相关的操作(比如sh、stage)转换成CPS兼容的形式,这样才能正确跟踪执行状态、处理异步逻辑,以及在需要时序列化/恢复流水线上下文。

而你给buildDriver添加了@NonCPS注解,这会让Jenkins绕过对该方法的CPS转换。但你在方法内部返回的闭包里,又包含了大量Jenkins流水线API的调用——当你调用闭包的run()方法时,这些API调用无法被CPS机制正确跟踪,导致shell命令执行完成后,Jenkins找不到回到原执行上下文的路径,最终陷入无限阻塞。

解决方案

方案1:移除@NonCPS注解

直接去掉buildDriver方法上的@NonCPS,让Jenkins对这个方法和它返回的闭包进行CPS转换,这样就能正常跟踪执行流程了:

class Device {
    def context
    public Device(context) {
        this.context = context
    }
    // 移除@NonCPS注解
    def buildDriver() {
        return ({
            context.stage("Build Driver") {
                context.script {
                    context.print("111111111111")
                    context.sh("pwd;")
                    context.print("222222222222")
                    context.sh("ls -al")
                    context.print("333333333333")
                }
            }
        })
    }
}
dev = new Device(this)
pipeline {
    agent any
    stages {
        stage("main stage") {
            steps {
                script {
                    print("start script")
                    dev.buildDriver().run()
                }
            }
        }
    }
}

方案2:直接执行流水线步骤(更推荐)

其实完全没必要返回闭包,直接在buildDriver方法内部执行流水线步骤即可,这种写法更符合Jenkins的执行逻辑,也能从根源上避免闭包带来的上下文跟踪问题:

class Device {
    def context
    public Device(context) {
        this.context = context
    }
    def buildDriver() {
        context.stage("Build Driver") {
            context.script {
                context.print("111111111111")
                context.sh("pwd;")
                context.print("222222222222")
                context.sh("ls -al")
                context.print("333333333333")
            }
        }
    }
}
dev = new Device(this)
pipeline {
    agent any
    stages {
        stage("main stage") {
            steps {
                script {
                    print("start script")
                    // 直接调用方法,无需run()
                    dev.buildDriver()
                }
            }
        }
    }
}

注意事项

在Jenkins自定义类中使用流水线API时,记住这一点:

  • @NonCPS注解只适合处理纯Groovy业务逻辑(比如字符串处理、数据计算、工具类方法),绝对不能用它包裹涉及Jenkins流水线步骤(sh、stage、script等)的方法,否则会破坏CPS的执行跟踪机制,引发各种奇怪的问题。

内容的提问来源于stack exchange,提问作者김현준

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 17:52:50