Jenkinsfile中Groovy创建JSON文件后Shell/Python无法访问问题
问题分析与解决
根本原因
你的Groovy方法加了@NonCPS注解,这会导致这段代码运行在Jenkins Master节点的JVM中,直接使用java.io.File类操作的是Master的文件系统。而后续的sh步骤如果是在Slave/Agent节点上执行的,WORKSPACE指向的是Agent的本地工作目录——两边的文件系统完全隔离,所以Shell自然找不到Master上创建的文件。
从日志也能佐证这点:Groovy返回的文件路径虽然和Shell的pwd输出一致,但实际是Master上的对应路径,和Agent的同名路径不是同一个位置。
解决方案
方案1:改用Jenkins Pipeline原生文件操作步骤(推荐)
去掉@NonCPS注解,使用Jenkins提供的writeFile、readFile步骤,这些步骤是CPS兼容的,会自动在当前执行的Agent节点上操作文件,无需关心节点差异。
修改后的datastore.groovy代码:
def set_var(String workspaceDir, String text) { def filePath = "${workspaceDir}/datastore.json" def data = [:] // 读取现有文件(如果存在) if (fileExists(filePath)) { def existingContent = readFile(filePath) data = new groovy.json.JsonSlurper().parseText(existingContent) } // 更新数据 data["text"] = text def json = groovy.json.JsonOutput.toJson(data) // 写入文件 writeFile(file: filePath, text: json) // 验证文件存在并返回信息 def files = findFiles(glob: "${workspaceDir}/*").collect { it.name }.join("\n") return "Wrote text: ${text} to file: ${filePath}; files: ${files}" }
方案2:确保Groovy代码与Shell步骤在同一节点执行
如果必须保留@NonCPS和java.io.File操作,要确保整个代码块都在同一个Agent节点上运行。可以通过node块指定Agent,让Groovy和Shell都在该节点执行:
修改Jenkinsfile:
stage { steps { node("your-agent-label") { // 指定你的Agent标签 script { if (foo.bar()) { echo "set_var: " + datastore.set_var(WORKSPACE, "meow") sh(script: "pwd ; ls -l") } } } } }
注意:这种方式需要确保Agent节点的文件系统能被Groovy的File类访问到,本质是让@NonCPS代码在Agent节点的JVM中执行(需要Agent是Java节点),否则仍会有问题。
验证要点
修改后重新运行Pipeline,检查:
- Groovy返回的文件路径对应的是Agent节点的实际目录
- Shell的
ls输出能看到datastore.json文件
内容的提问来源于stack exchange,提问作者Gavriel
相关产品推荐
相关产品推荐

