Last active
May 7, 2019 14:11
-
-
Save leonschreuder/df1174d2c1d84e7fe8db8710cd7beff1 to your computer and use it in GitHub Desktop.
execute command in groovy.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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