用Java程序來控制shell腳本的運行和停止。具體來講,這個Java程序至少要有三個功能:
- 運行Shell腳本;
- 等待Shell腳本執行結束;
- 停止運行中的Shell程序;
從功能需求來看,似乎是比較容易做到的。儘管沒有寫過類似功能的程序,Google一下,很快就有答案了。
用Runtime或者ProcessBuilder可以運行程序,而Process類的waitFor()和destroy()方法分別滿足功能2和3。
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
public class ShellRunner extends Thread
{
private Process proc;
private String dir;
private String shell;
public ShellRunner(String dir, String shell)
{
super();
this.proc = null;
this.dir = dir;
this.shell = shell;
}
@Override
public void run() {
try
{
ProcessBuilder builder = new ProcessBuilder("sh", dir + shell);
builder.directory(new File(dir));
proc = builder.start();
System.out.println("Running ...");
int exitValue = proc.waitFor();
System.out.println("Exit Value: " + exitValue);
}
catch (IOException e)
{
e.getLocalizedMessage();
}
catch (InterruptedException e)
{
e.getLocalizedMessage();
}
}
public void kill()
{
if (this.getState() != State.TERMINATED) {
proc.destroy();
}
}
public static void main(String args[]) {
ShellRunner runner = new ShellRunner("/tmp/", "run.sh");
runner.start();
InputStreamReader inputStreamReader = new InputStreamReader(System.in);
BufferedReader reader = new BufferedReader(inputStreamReader);
try
{
String line = null;
while ( (line = reader.readLine()) != null ) {
if (line.equals("kill")) {
runner.kill();
}
else if (line.equals("break")) {
break;
}
else {
System.out.println(runner.getState());
}
}
reader.close();
inputStreamReader.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
waitFor()方法可以正確等待shell程序退出,但是destroy()方法並沒有結束shell腳本相關的進程。
這是一個BUG。
JDK-bug-4770092:Process.destroy()不能結束孫子進程(grandchildren)。