概述
Java执行系统命令,典型的方式,通过以下两个类来实现
- Runtime
- ProcessBulider
Runtime
- Runtime是一个单例的实例
- Runtime运行应用程序与运行应用程序的环境进行交互
- Runtime是Java运行时环境,应用程序不能创建属于自己的实例,需要通过getRuntime()方法获取
- 代码实例
private Process exec(String command) throws IOException {
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec(command);
return process;
}
ProcessBulider
- ProcessBulider用来创建操作系统进程
- 使用start方法,可以重复创建新的子进程
- 代码实例
private Process start(String command) throws IOException {
//将一整条命令转成String数组
StringTokenizer st = new StringTokenizer(command);
String[] cmdarray = new String[st.countTokens()];
for (int i = 0; st.hasMoreTokens(); i++) {
cmdarray[i] = st.nextToken();
}
ProcessBuilder builder = new ProcessBuilder(cmdarray);
Process process = builder.start();
return process;
}
Runtime与ProcessBuilder实现执行系统命令的区别
- 本质两种方式并没有什么区别,
Runtime.getRuntime().exec(command)
方法内部也是调用new ProcessBuilder().command(command).start()
方法 - Runtime的exec方法
public Process exec(String[] cmdarray, String[] envp, File dir)throws IOException {
return new ProcessBuilder(cmdarray)
.environment(envp)
.directory(dir)
.start();
}
Process
- 通过
ProcessBuilder#start()
或Runtime#exec()
创建一个进程,同时返回一个Process实例 - Process实例可以控制该进程和获取进程信息,如输出的错误日志等
- 方法
- getOutputStream
- getInputStream
- getErrorStream
- 获取命令执行中的错误日志
- waitFor
- 当前进程进入等待状态,直到该进程结束或退出
- waitFor(long,TimeUnit)
- exitValue
- destroy
- 终止该进程
- destroyForcibly
- isAlive
问题记录
- 子进程(Process)的输出和错误信息过多时会导致进程阻塞住,执行不下去
- 主动取出输出和错误日志
public static void main(String[] args) throws IOException {
String command="Ping 192.168.1.16";
Process start = start(command);
InputStream is = start.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is,Charset.forName("gbk")));
String message;
while((message=br.readLine())!=null){
System.out.println(message);
}
InputStream errorStream = start.getErrorStream();
while(errorStream.read()!=-1){}
}
- 但是当遇到像ffmpeg的拉流推流命令,这种会不停的输出日志信息的情况,使用以上方式将信息不断取出,也是不合适的,最好就是控制日志的输出