Skip to content

Instantly share code, notes, and snippets.

@leonschreuder
Last active May 7, 2019 14:11
Show Gist options
  • Save leonschreuder/df1174d2c1d84e7fe8db8710cd7beff1 to your computer and use it in GitHub Desktop.
Save leonschreuder/df1174d2c1d84e7fe8db8710cd7beff1 to your computer and use it in GitHub Desktop.
execute command in groovy.
package de.esolutions.gradle.plugin
import java.util.concurrent.TimeUnit
/** Running a command should be a simple "command".execute() in groovy, but reading
* output and making the command time-out at the same time, is somehow buggy and the
* process won't quit if it hangs.
* Thanks: https://stackoverflow.com/a/33265110/3968618
* */
class RunCommandBuilder {
private File workingDir
private long timeoutInMillis
private String[] command
private final int incrementsInMillis = 1000
public static RunCommandBuilder builder() {
return new RunCommandBuilder()
}
public RunCommandBuilder setWorkigDir(File workingDir) {
this.workingDir = workingDir
return this
}
public RunCommandBuilder setCommand(String ... command) {
this.command = command
return this
}
public RunCommandBuilder setTimeoutInSeconds(int timeout) {
this.timeoutInMillis = TimeUnit.MILLISECONDS.convert(timeout, TimeUnit.SECONDS)
return this
}
public void buildAndRun() {
println("Running Command " + Arrays.toString(command))
ProcessBuilder processBuilder = new ProcessBuilder(Arrays.asList(command))
if (workingDir != null)
processBuilder.directory(workingDir)
processBuilder.redirectErrorStream(true)
Process process = processBuilder.start() //Executing the process
BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream()));
waitForTimeout(input, process); //Waiting for Timeout
String line;
while ((line = input.readLine()) != null) {
println(line)
}
}
/** block the thread until the command is finished, or the timeout is reached. The normal
* process.waitOrKill() doesn't seem to wait if we read the output. */
private void waitForTimeout(BufferedReader input, Process process) throws InterruptedException, Exception {
while (timeoutInMillis > 0) {
if (input.ready()) {
break;
} else {
timeoutInMillis -= incrementsInMillis
Thread.sleep(incrementsInMillis)
if (timeoutInMillis == 0 && !input.ready()) {
process.destroyForcibly()
println("Command timed out. Killing process...")
throw new Exception("Timeout in executing the command.")
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment