执行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
相关产品推荐
相关产品推荐

