在Groovy中执行代码时出现Stream Closed错误,如何排查解决?
Let's break down what's happening and how to resolve this issue.
What's causing the "Stream closed" error?
While Groovy's withInputStream is supposed to handle opening and closing the stream safely for you, in a Jenkins pipeline context, there are a few likely culprits:
- Incorrect workspace path: If you're using a declarative Jenkins pipeline, using
${WORKSPACE}directly might not resolve properly—you need to referenceenv.WORKSPACEinstead. Even if the error doesn't say "file not found", a malformed path can lead to unexpected stream behavior. - Jenkins/Groovy compatibility oddities: Sometimes the automatic stream management in
withInputStreamclashes with Jenkins' sandbox or classloader setup, causing the stream to close before yourproperties.load()call finishes. - Premature stream closure: While less likely here, if any underlying code (like a custom plugin) closes the stream early inside the closure, you'll hit this error.
Fixes to try
Here are a few reliable solutions to get past this error:
1. Ditch withInputStream for explicit stream handling
Taking full control of opening and closing the stream with a try-finally block avoids any unexpected behavior from Groovy's automatic management:
Properties properties = new Properties() File propertiesFile = new File("${env.WORKSPACE}/sonar-project.properties") InputStream inputStream = null try { inputStream = new FileInputStream(propertiesFile) properties.load(inputStream) } catch (IOException e) { echo "Oops, failed to load properties: ${e.message}" throw e // Let the pipeline fail if this is critical } finally { if (inputStream != null) { try { inputStream.close() } catch (IOException e) { echo "Warning: Had trouble closing the stream: ${e.message}" } } } echo properties."sonar.sources"
2. Double-check your workspace path
First, confirm you're pointing to the right file. Add these debug lines to your pipeline to verify:
def propsFilePath = "${env.WORKSPACE}/sonar-project.properties" echo "Looking for properties file at: ${propsFilePath}" echo "File exists? ${new File(propsFilePath).exists()}" echo "Can read file? ${new File(propsFilePath).canRead()}"
In declarative pipelines, always use env.WORKSPACE—bare ${WORKSPACE} might not resolve correctly.
3. Use Groovy's simpler file reading shortcuts
Groovy has cleaner ways to load properties without dealing with streams directly. Try this concise approach:
def properties = new File("${env.WORKSPACE}/sonar-project.properties").withReader { reader -> new Properties().tap { load(reader) } } echo properties."sonar.sources"
Or even more straightforward:
Properties properties = new Properties() properties.load(new File("${env.WORKSPACE}/sonar-project.properties").newReader()) echo properties."sonar.sources"
Quick additional checks
- Make sure the Jenkins agent has read permissions for the
sonar-project.propertiesfile. - Ensure the file isn't locked by another process (like a previous build step that didn't release the file handle).
内容的提问来源于stack exchange,提问作者Karl

