本文主要介绍Java中使用ProcessBuilder或Runtime.exec()调用系统命令的方法代码,也就是调用windows系统中cmd命令或者调用Linux系统中sh命令(shell命令),以及是否为windows操作系统的判断。

1、操作系统判断

boolean isWindows = System.getProperty("os.name")
.toLowerCase().startsWith("windows");

2、读取调用命令的输出

输出(Output)必须被读取,否则我们的进程将挂起,不能成功返回。

通过StreamGobbler类来读取InputStream:

private static class StreamGobbler implements Runnable {
private InputStream inputStream;
private Consumer<String> consumer;
public StreamGobbler(InputStream inputStream, Consumer<String> consumer) {
this.inputStream = inputStream;
this.consumer = consumer;
}
@Override
public void run() {
new BufferedReader(new InputStreamReader(inputStream)).lines()
.forEach(consumer);
}
}

3、使用Runtime.exec()调用cmd命令和shell命令并将结果输出到控制台

String homeDirectory = System.getProperty("user.home");
Process process;
if (isWindows) {
process = Runtime.getRuntime()
.exec(String.format("cmd.exe /c dir %s", homeDirectory));
} else {
process = Runtime.getRuntime()
.exec(String.format("sh -c ls %s", homeDirectory));
}
StreamGobbler streamGobbler =
new StreamGobbler(process.getInputStream(), System.out::println);
Executors.newSingleThreadExecutor().submit(streamGobbler);
int exitCode = process.waitFor();
assert exitCode == 0;

4、使用ProcessBuilder调用cmd命令和shell命令并将结果输出到控制台

对于有些复杂的处理,可以使用ProcessBuilder,使用它可以:

  • 使用builder.directory()更改我们的shell命令正在运行的工作目录
  • 使用builder.environment()将自定义键值映射设置为环境变量
  • 将输入和输出流重定向到自定义替换
  • 使用builder.inheritIO()将它们都继承到当前JVM进程的流

ProcessBuilder builder = new ProcessBuilder();
if (isWindows) {
builder.command("cmd.exe", "/c", "dir");
} else {
builder.command("sh", "-c", "ls");
}
builder.directory(new File(System.getProperty("user.home")));
Process process = builder.start();
StreamGobbler streamGobbler =
new StreamGobbler(process.getInputStream(), System.out::println);
Executors.newSingleThreadExecutor().submit(streamGobbler);
int exitCode = process.waitFor();
assert exitCode == 0;

参考文档:https://www.baeldung.com/run-shell-command-in-java