I have a gradle task I wrote that runs something on the command line. The process takes ~15 seconds and writes its status to the console. I want to take action based on the status that is written to the console. I see the standardOutputStream property for an Exec task but anytime I println that it seems to print to the console first and then my process finally writes to the console. How do I handle this situation in gradle?
I’m not sure what exactly you’re exec’ing (which might have special output behavior that I’m not aware of)…
Could the process be sending things to std error that you’re not intercepting?
I am running my jasmine js unit tests via phantom js(headless webkit tool).
Here is my task definition on my local machine
task runJasmine(type: Exec) {
workingDir '/src/main/webapp/resources/js/tests/'
//windows
commandLine 'cmd', '/c', 'phantomjs jasmine_phantom.js SpecRunner.html results.html'
println 'execResult ' + execResult
println 'stdOut ' + standardOutput
println 'stdIn ' + standardInput
}
Here is the output I am seeing where the printlns in the task seem to print to the console before the script that is running phantom does.
execResult null stdOut org.apache.commons.io.output.CloseShieldOutputStream@1ef479c2 stdIn java.io.ByteArrayInputStream@4465bf6e :my-project:runJasmine
------------------------------------------------------- J A S M I N E
T E S T S -------------------------------------------------------
Test URL: SpecRunner.html Tests completed in 2408 ms Test results file: results.html Tests passed.
BUILD SUCCESSFUL
Total time: 19.377 secs
By default, forked processes write through to the parent processes stdout. This isn’t what you want. You want to collect the output and then parse it.
task runJasmine(type: Exec) {
workingDir '/src/main/webapp/resources/js/tests/'
//windows
commandLine 'cmd', '/c', 'phantomjs jasmine_phantom.js SpecRunner.html results.html'
standardOutput = new ByteArrayOutputStream()
doLast {
String output = standardOutput.toString()
}
}
The execResult is null because the task hasn’t ran yet.
Printing the standardOutput/input they way you do it is not quite right because:
-
you’re printing it at configuration phase
-
printing it only prints the string representation of the default stream (by default, Gradle uses System.out). If you want to get hold of the output, assign brand new ByteArrayOutputStream. Take a look at the example:
task foo(type: Exec) {
commandLine = //
//store the output instead of printing to the console
standardOutput = new ByteArrayOutputStream()
//extension method foo.output() can be used to obtain the output String
ext.output = {
return standardOutput.toString()
}
}
task showFooOutput(dependsOn: foo) {
doLast {
println "Foo's output: ${foo.output()}"
}
}
Hope that helps!
@Luke - This version of the task worked @Szczepan - I don’t understand this example 100%. Where is ext referring to? What is it? When I lookup exec task I don’t see ext as property listed (perhaps its inherited?).
ext refers to: http://gradle.org/docs/current/dsl/org.gradle.api.plugins.ExtraPropertiesExtension.html
Thanks that was really helpful. I never knew it existed
Do you guys have any suggestions on how to fail the build if that text indicates failure?
You can just throw an exception.