大致分为五步:创建环境、建立连接、发送数据、读取结果、释放资源。
下面我们以打开一个shell进程,在进程中执行pwd命令,然后退出为例,来看一下整个过程。
1、创建环境
主要有两个:执行程序和当前目录。这个和在命令行下执行一个普通的Linux程序一样,先有一个当前目录,然后在当前目录下面调用要执行的程序。我们运行pwd的话,就需要在一个目录下启动shell进程。当前目录我们可以随便选一个。这里选根目录。
ProcessBuilder pb = new ProcessBuilder("/system/bin/sh");
pb.directory(new File("/"));
2、建立连接
调用Process proc = pb.start()方法,获取对新建立的本地进程的引用。
通过proc这个引用我们就可以获取到向进程发送数据的输出流,并把向输出流写入的数据作为进程的输入:
OutStream os = proc.getOutputStream()
3、发送数据
每一个本地进程代表一个C/C++程序,这个程序在启动时需要一些输入数据,也就是main方法中传入的参数。这个需要通过向第二步得到的os写入数据来实现:
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(proc.getOutputStream())), true);
out.println("pwd");
//如果执行的本地程序是shell,exit这个命令一定要发送,否则shell这个本地进程结束不了,整个Java程序也会阻塞在第四步。
out.println("exit");
发送完数据后,我们可以调用proc.waitFor()来等待程序执行完毕后再继续,也可以直接进行第四步,读取结果。如果等待程序执行完毕后再读取结果的话,就是直接从缓冲区读取数据而不需要在读取的过程中阻塞来等待程序执行完毕了。
4、读取结果
这一步主要是把本地程序执行过程中的输出信息读取出来。
BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
5、销毁连接释放资源
in.close();
out.close();
proc.destroy();
当然,以上这些操作用Runtime.exec系列方法也可以完全做到。说到底,ProcessBuilder只是对Runtime.exec系列方法的一个封装。