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

执行Shell时Jenkins Pipeline抛出java.io.NotSerializableException: hudson.model.User异常

解决Jenkins Pipeline的java.io.NotSerializableException: hudson.model.User异常

我刚踩过一模一样的坑,太懂这个糟心的问题了!这个异常本质是Jenkins Pipeline的序列化机制在搞事情——声明式Pipeline会自动序列化上下文里的所有变量来持久化状态,而你用input步骤返回的promoteMap里,偷偷包含了hudson.model.User类型的对象(就是触发这个输入操作的用户信息),但这个类没实现Serializable接口,所以序列化的时候直接炸了。

给你几个实用的解决方案,结合你的代码来改:

方案1:只提取需要的参数值(最推荐)

不要保存input返回的完整对象,只把你需要的参数值抽出来用。比如你的input是让用户输入build编号,那直接取这个字符串就行:

pipeline { 
    agent none 
    stages { 
        stage("PromoteBuild") { 
            agent { label "test_agent" } 
            steps { 
                script { 
                    def mopName = "mop name" // 用def声明局部变量,避免全局变量被序列化
                    try { 
                        timeout(time: 30, unit: 'SECONDS') { 
                            // 直接提取输入的参数值,而非保存整个返回对象
                            def selectedBuildNumbers = input(
                                id: 'promote', 
                                message: 'Choose bundled buildNumbers', 
                                ok: 'Promote?', 
                                parameters: [ 
                                    string(
                                        defaultValue: mopName,
                                        name: 'BUILD_NUMBERS',
                                        description: 'Enter bundled build numbers'
                                    )
                                ] 
                            )
                            // 执行你的Shell步骤,比如这里模拟promoteBuild
                            echo "Starting promotion for builds: ${selectedBuildNumbers}"
                            sh "echo Promoting build numbers ${selectedBuildNumbers}" // 替换成你的实际Shell命令
                        } 
                    } catch (Exception e) {
                        echo "Input was cancelled or timed out: ${e.message}"
                    }
                } 
            } 
        } 
    } 
}

方案2:用@NonCPS注解隔离不可序列化代码

如果你必须用到input返回的完整对象,可以把处理这个对象的逻辑放到标记了@NonCPS的方法里——Jenkins不会序列化@NonCPS标记的代码块,完美避开序列化问题:

pipeline { 
    agent none 
    stages { 
        stage("PromoteBuild") { 
            agent { label "test_agent" } 
            steps { 
                script { 
                    def mopName = "mop name" 
                    try { 
                        timeout(time: 30, unit: 'SECONDS') { 
                            def promoteMap = input(
                                id: 'promote', 
                                message: 'Choose bundled buildNumbers', 
                                ok: 'Promote?', 
                                parameters: [ 
                                    string(
                                        defaultValue: mopName,
                                        name: 'BUILD_NUMBERS',
                                        description: 'Enter bundled build numbers'
                                    )
                                ] 
                            )
                            // 交给@NonCPS方法处理,避免序列化promoteMap
                            handlePromotion(promoteMap)
                        } 
                    } catch (Exception e) {
                        echo "Input was cancelled or timed out: ${e.message}"
                    }
                } 
            } 
        } 
    } 
}

// 用@NonCPS标记,这个方法里的代码不会被Jenkins序列化
@NonCPS
def handlePromotion(promoteData) {
    def buildNumbers = promoteData['BUILD_NUMBERS']
    echo "Processing promotion for builds: ${buildNumbers}"
    sh "echo Promoting build numbers ${buildNumbers}" // 替换成你的实际Shell命令
}

关键注意点

  • 尽量用def声明局部变量,别用全局变量——全局变量会被Jenkins持久化序列化,更容易踩这个坑
  • input步骤的返回值不止包含用户输入的参数,还附带了用户信息、触发时间等元数据,这些元数据里就有不可序列化的User对象,所以别直接保存整个返回值
  • 如果你的Pipeline里还有其他不可序列化的对象(比如某些第三方库的实例),都可以用@NonCPS来隔离处理

内容的提问来源于stack exchange,提问作者Phoenix

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:54:33