如何杀死runtime.exec?

我在我的jframe中使用下面的代码,以便通过java程序执行shell脚本,但是当我实现其他方法来停止运行过程时,此方法被第一个阻止,我无法停止我的程序。 所以我要杀死新进程,问题是如何获取进程的pid以及如何将其置于后台,以便杀死它。

public static void execShellCmd(String cmd) { try { testPath = getPath(); System.out.println(cmd); Runtime runtime = Runtime.getRuntime(); process = runtime.exec(new String[] { "sh", testPath + "/install.sh", cmd, "&" }); int exitValue = process.waitFor(); value = exitValue; System.out.println("exit value: " + exitValue); BufferedReader buf = new BufferedReader(new InputStreamReader( process.getInputStream())); String line = ""; BufferedWriter bufferedWriter = null; while ((line = buf.readLine()) != null) { System.out.println("exec response: " + line); log = line; writeToFile(line); } } catch (Exception e) { System.out.println(e); } } 

为此,您可以使用java.util.concurrent中提供的function

在包含UI的现有类中,您必须添加类似于此的内容:

 //class variable to store the future of your task private Future taskFuture = null; //to be called from button "Start" action handler public void actionStart() { //don't double start, if there is one already running if(taskFuture == null || taskFuture.isDone()) { //create the new runnable instance, with the proper commands to execute MyShellExecutor ex = new MyShellExecutor(new String[] { "sh",testPath + "/install.sh", cmd, "&" }); //we only need one additional Thread now, but this part can be tailored to fit different needs ExecutorService newThreadExecutor = Executors.newSingleThreadExecutor(); //start the execution of the task, which will start execution of the shell command taskFuture = newThreadExecutor.submit(ex); } } //to be called from button "Stop" action handler public void actionStop() { //if not already done, or cancelled, cancel it if(taskFuture !=null && !taskFuture.isDone()) { taskFuture.cancel(true); } } 

执行该作业的主要组件是Runnable ,我将其命名为MyShellExecutor ,如下所示:

 public class MyShellExecutor implements Runnable { //stores the command to be executed private final String[] toExecute; public MyShellExecutor(String[] toExecute) { this.toExecute=toExecute; } public void run() { Runtime runtime = Runtime.getRuntime(); Process process = null; try { process = runtime.exec(toExecute); int exitValue = process.waitFor(); System.out.println("exit value: " + exitValue); BufferedReader buf = new BufferedReader(new InputStreamReader(process.getInputStream())); String line = ""; while ((line = buf.readLine()) != null) { System.out.println("exec response: " + line); //do whatever you need to do } } catch (InterruptedException e) { //thread was interrupted. if(process!=null) { process.destroy(); } //reset interrupted flag Thread.currentThread().interrupt(); } catch (Exception e) { //an other error occurred if(process!=null) { process.destroy(); } } } } 

注意:在运行耗时的操作时,请确保不要在UI线程上执行此操作。 这只是阻止用户,并没有提供良好的用户体验。 总是做一些可能让用户在另一个线程上等待的东西。

推荐阅读: Java Concurrency In Practice

如果您的“其他方法”可以访问原始exec返回的Process对象,那么您只需调用process.destroy()来终止正在运行的进程。 您不需要知道本机PID。 这是使用SwingWorker的一个或多或少的完整示例(可能有一些我忘记的try / catch块):

 private Process runningProcess = null; public static void execShellCmd(String cmd) { if(runningProcess != null) { // print some suitable warning about process already running return; } try { testPath = getPath(); System.out.println(cmd); Runtime runtime = Runtime.getRuntime(); runningProcess = runtime.exec(new String[] { "sh", testPath + "/install.sh", cmd }); new SwingWorker() { protected Integer doInBackground() { // read process output first BufferedReader buf = new BufferedReader(new InputStreamReader( process.getInputStream())); String line = ""; while ((line = buf.readLine()) != null) { System.out.println("exec response: " + line); log = line; writeToFile(line); } // only once we've run out of output can we call waitFor while(true) { try { return runningProcess.waitFor(); } catch(InterruptedException e) { // do nothing, wait again } finally { Thread.interrupted(); } } return -1; } protected void done() { runningProcess = null; } }.execute(); } } public static void stopProcess() { if(runningProcess != null) { runningProcess.destroy(); } } 

只要execShellCmdstopProcess只从事件调度线程调用,那么就不需要同步,因为对runningProcess字段的所有访问都发生在同一个线程上( SwingWorker一点就是doInBackground发生在工作线程上但是运行done了EDT)。