I am executing a shell script from my Java program using Process
and I want to kill/destroy that process if my script takes long time.
I came up with this code and wanted to see if there is any better way or anything I can improve on.
public class Test {
public static void main(String[] args) throws IOException, InterruptedException {
// Your script
String script = getScriptTextFromSomewhere();
// create a temp file and write your script to it
File tempScript = File.createTempFile("temp_scripts_", "");
tempScript.setExecutable(true);
try (OutputStream output = new FileOutputStream(tempScript)) {
output.write(script.getBytes());
}
// build the process object and start it
List<String> commandList = new ArrayList<>();
commandList.add(tempScript.getAbsolutePath());
ProcessBuilder builder = new ProcessBuilder(commandList);
builder.redirectErrorStream(true);
builder.environment().put("param1", "abc");
builder.environment().put("param2", "xyz");
Process shell = builder.start();
// read the output and show it
try (BufferedReader reader = new BufferedReader(new InputStreamReader(shell.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
// wait for the process to finish
WaitingThread thread = new WaitingThread(shell);
thread.start();
long timeoutMillis = 20000;
thread.join(timeoutMillis);
if(thread.isAlive()) {
thread.interrupt();
}
if(!thread.isFinished()) {
shell.destroy();
shell.waitFor();
System.out.println("PROCESS WAS INTERRUPTED");
} else {
// check the exit code (exit code = 0 usually means "executed ok")
System.out.println("PROCESS FINISHED, EXIT CODE: " + thread.getExitValue());
}
// delete temp file
tempScript.delete();
}
}
class WaitingThread extends Thread {
private int exitValue;
private Process shell;
private boolean finished = false;
public WaitingThread(Process shell) {
this.shell = shell;
}
@Override
public void run() {
try {
exitValue = shell.waitFor();
finished = true;
} catch (InterruptedException e) {
finished = false;
}
}
public int getExitValue() {
return exitValue;
}
public boolean isFinished() {
return finished;
}
}