当前位置: 首页 > news >正文

Jenkins Pipeline 中使用 JsonSlurper 报错:cannot find current thread

Jenkins Pipeline 中使用 JsonSlurper 报错:cannot find current thread

  • 🌟 背景
  • ⚠ 问题重现
  • 🧠 原因解析:CPS 与非 CPS 安全方法冲突
  • ✅ 解决方案一:使用 @NonCPS 注解(经典方案)
  • ✅ 解决方案二:使用 `readJSON` 步骤(推荐)
  • ✅ 解决方案三:完全在 `script {}` 中处理(适合小范围)
  • 🔁 最佳实践推荐
  • ❌ 避免的错误写法
  • 📌 总结

🌟 背景

在 Jenkins 声明式 Pipeline 中,有时我们需要解析一段 JSON 字符串,例如部署路径、构建参数等。在 Groovy 中,最常见的方式是使用 JsonSlurper

def jsonData = new groovy.json.JsonSlurper().parseText(myJsonText)

然而,在 Jenkins 中你很可能会遇到如下报错:

java.io.IOException: cannot find current thread

这类报错常常让人摸不着头脑。为什么在 Groovy 中正常工作的代码,在 Jenkins Pipeline 中却报错?


⚠ 问题重现

pipeline {agent anystages {stage('Parse JSON') {steps {script {def jsonText = '[{"src":"/a","dest":"/b"}]'def deployList = new groovy.json.JsonSlurper().parseText(jsonText) // 报错行}}}}
}

运行报错:

Cannot contact <node>: java.io.IOException: cannot find current thread

🧠 原因解析:CPS 与非 CPS 安全方法冲突

Jenkins Pipeline 基于 Groovy CPS(Continuation Passing Style)转换机制 实现“流水线可恢复性”。这意味着:

  • Pipeline 中的脚本会被 Jenkins 转换成 CPS 代码
  • CPS 会将执行状态保存到磁盘,以支持“中断恢复”、“断点续跑”
  • 然而,一些方法(如 JsonSlurper.parseText())不是 CPS 安全的,即不能被 Jenkins 正确序列化和恢复

✴ 为什么会报错?

JsonSlurper 会在底层调用 Thread.currentThread()、或使用 Java 原生 IO API,这在 CPS 上下文中是不被支持的操作。因此 Jenkins 抛出:

java.io.IOException: cannot find current thread

本质上,是 Jenkins 的 CPS 执行引擎无法“保存你执行的上下文状态”。


✅ 解决方案一:使用 @NonCPS 注解(经典方案)

将解析方法单独封装,并添加 @NonCPS 注解:

@NonCPS
def parseDeployPath(String jsonText) {try {if (jsonText == null || jsonText.trim() == "") {// 输入为空,返回空列表return []}def rawList = new groovy.json.JsonSlurper().parseText(jsonText)def simpleList = rawList.collect { item -> [src: item.src.toString(), dest: item.dest.toString()]}return simpleList} catch (Exception e) {println "❌ JSON 解析 deployPath 失败:${e.message}"return null}
}pipeline {agent anystages {stage('Parse') {steps {script {def json = '[{"src":"/a","dest":"/b"}]'def deployList = parseDeployPath(json)echo "Deploy List: ${deployList}"}}}}
}

为什么可行?

使用 @NonCPS 修饰的方法,不会被 Jenkins 的 CPS 引擎转换,因此可以使用原生 Groovy 方法,但代价是:

  • 无法使用 DSL(如 sh, echo 等)
  • 方法内不可访问 Pipeline 变量(如 env, params

✅ 解决方案二:使用 readJSON 步骤(推荐)

安装插件:Pipeline Utility Steps

pipeline {agent anystages {stage('Parse JSON safely') {steps {script {writeFile file: 'deploy.json', text: '[{"src":"/a","dest":"/b"}]'def deployList = readJSON file: 'deploy.json'deployList.each {echo "src: ${it.src}, dest: ${it.dest}"}}}}}
}

优势:

  • readJSON 是 Jenkins 官方提供的 DSL 级方法
  • 完全支持 流水线序列化和恢复
  • 不需要使用 @NonCPS

✅ 解决方案三:完全在 script {} 中处理(适合小范围)

虽然 JsonSlurper 本身不是 CPS 安全的,但在某些场景下,如果你在 script {} 中直接使用它,而没有调用嵌套函数,也能正常工作。

script {def json = '[{"src":"/a","dest":"/b"}]'def list = new groovy.json.JsonSlurper().parseText(json)list.each {echo "src: ${it.src}, dest: ${it.dest}"}
}

⚠ 注意:这种方式不一定在所有 Jenkins 环境中都安全,视具体版本而定。


🔁 最佳实践推荐

场景推荐方式
生产级流水线中解析 JSONreadJSON
工具方法、辅助转换@NonCPS
快速测试、数据调试script { JsonSlurper }

❌ 避免的错误写法

不要这样写:

def deployList = new groovy.json.JsonSlurper().parseText(params.jsonData)

或嵌套在函数中调用:

def parseIt() {return new JsonSlurper().parseText('...')
}

✅ 改为 @NonCPS 修饰 或使用 readJSON


📌 总结

Jenkins Pipeline 中,Groovy 方法并非都能直接使用。受限于 Jenkins 的 CPS 系统,很多涉及 IO、线程、状态不可序列化的操作会报错。面对 JsonSlurper 报错,推荐采用:

  • 首选:使用 Jenkins DSL 提供的 readJSON + writeFile
  • 通用:将 JSON 操作封装为 @NonCPS 方法
  • 调试:仅在 script {} 中临时使用 JsonSlurper

http://www.xdnf.cn/news/1130923.html

相关文章:

  • 55. 跳跃游戏
  • 2025年中国品牌全球化发展分析:中国品牌在社交渠道、电商平台及官网流量方面显著增长
  • 语音增强论文汇总
  • IIS网站间歇性打不开暴力解决方法
  • 【数据结构】栈与链表的区别
  • 【Qt开发】Qt的背景介绍(二)-> 搭建Qt开发环境
  • 如何在硬件中进行有效地调试
  • TCP 三次握手与四次挥手笔记
  • 前端vue3获取excel二进制流在页面展示
  • Promise与Axios:异步编程
  • sqli-labs靶场通关笔记:第23关 注释符过滤
  • React -自定义hooks - 封装双向数据绑定
  • 自动控制原理知识地图:舵轮、路径与导航图
  • 2025年C++后端开发高频面试题深度解析:线程安全LRU缓存设计与实现
  • C# StringBuilder源码分析
  • 2025年Java最新社招面试八股文+技术场景题(金九银十)
  • Hadoop架构演进:从1.0到2.0的深度对比与优化解析
  • Hadoop(二)
  • QT技巧之快速搭建串口收发平台
  • Taro.getRandomValues() 用法详解
  • 有哪些好用的原型设计软件?墨刀、Axure等测评对比
  • Elasticsearch+Logstash+Kibana部署
  • Taro.eventCenter 用法详解与实战
  • 深入核心:理解Spring Boot的三大基石:起步依赖、自动配置与内嵌容器
  • 【Qt+error】error: use of undeclared identifier ‘MainWindow
  • uniapp各端通过webview实现互相通信
  • qt 中英文翻译 如何配置和使用
  • Spring AI 系列之十三 - RAG-加载本地嵌入模型
  • 在 CentOS 8 上彻底卸载 Kubernetes(k8s)
  • k8s之持久化存储流程