1.创建ProcessBuilder
根据不同的操作系统,构建不同的命令参数,
unix系统的命令参数为 bash -c
,
windows系统的命令参数为cmd /c
ProcessBuilder processBuilder = new ProcessBuilder();
if (isUnix) {
processBuilder.command("bash", "-c", String.join(" ", cmd));
} else {
processBuilder.command("cmd", "/c", String.join(" ", cmd));
}
Process process = processBuilder.start();
2. 创建线程池,获取输出结果
需要读取正常输出和异常输出
ExecutorService executorService = Executors.newFixedThreadPool(2);
Future<byte[]> outputFuture = executorService.submit(() -> readStream(process.getInputStream()));
Future<byte[]> errorFuture = executorService.submit(() -> readStream(process.getErrorStream()));
其中readStream方法的作用是读取输出流,将其转换为字节数组
private byte[] readStream(InputStream inputStream) {
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
byte[] buff = new byte[128];
int length = -1;
while ((length = inputStream.read(buff)) != -1) {
baos.write(buff, 0, length);
}
return baos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
return new byte[0];
}
}
3.构建一个工具类,用于保存输出结果
output为正常输出结果,
error为异常输出,
exitCode为程序退出值,正常值为0
public static class CommandResult {
private final byte[] output;
private final byte[] error;
private final int exitCode;
public CommandResult(byte[] output, byte[] error, int exitCode) {
this.output = output;
this.error = error;
this.exitCode = exitCode;
}
public byte[] getOutput() {
return output;
}
public byte[] getError() {
return error;
}
public int getExitCode() {
return exitCode;
}
}
4.等待执行完毕
executorService.shutdown();
if (executorService.awaitTermination(10, TimeUnit.SECONDS)) {
System.out.println("线程执行完毕");
int exitCode = process.waitFor();
executorService.close();
return new CommandResult(outputFuture.get(), errorFuture.get(), exitCode);
} else {
System.out.println("线程超时");
process.destroy();
executorService.close();
return new CommandResult(null, null, -1);
}
5.完整代码如下
/**
* 执行本地命令,等待命令执行完毕,获取执行结果和异常信息
*/
public class LocalCommandExecutor {
private final String[] cmd;
private final boolean isUnix;
public LocalCommandExecutor(boolean isUnix, String... cmd) {
this.isUnix = isUnix;
this.cmd = cmd;
}
public CommandResult execute() throws IOException, InterruptedException, ExecutionException {
ProcessBuilder processBuilder = new ProcessBuilder();
if (isUnix) {
processBuilder.command("bash", "-c", String.join(" ", cmd));
} else {
processBuilder.command("cmd", "/c", String.join(" ", cmd));
}
Process process = processBuilder.start();
ExecutorService executorService = Executors.newFixedThreadPool(2);
Future<byte[]> outputFuture = executorService.submit(() -> readStream(process.getInputStream()));
Future<byte[]> errorFuture = executorService.submit(() -> readStream(process.getErrorStream()));
executorService.shutdown();
if (executorService.awaitTermination(10, TimeUnit.SECONDS)) {
System.out.println("线程执行完毕");
int exitCode = process.waitFor();
executorService.close();
return new CommandResult(outputFuture.get(), errorFuture.get(), exitCode);
} else {
System.out.println("线程超时");
process.destroy();
executorService.close();
return new CommandResult(null, null, -1);
}
}
private byte[] readStream(InputStream inputStream) {
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
byte[] buff = new byte[128];
int length = -1;
while ((length = inputStream.read(buff)) != -1) {
baos.write(buff, 0, length);
}
return baos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
return new byte[0];
}
}
public static class CommandResult {
private final byte[] output;
private final byte[] error;
private final int exitCode;
public CommandResult(byte[] output, byte[] error, int exitCode) {
this.output = output;
this.error = error;
this.exitCode = exitCode;
}
public byte[] getOutput() {
return output;
}
public byte[] getError() {
return error;
}
public int getExitCode() {
return exitCode;
}
}
}
6.测试类如下
public static void main(String[] args) throws IOException, ExecutionException, InterruptedException {
String command = "echo Hello, World!";
command = "xxxx";
LocalCommandExecutor2 localCommandExecutor = new LocalCommandExecutor2(false, command);
CommandResult commandResult = localCommandExecutor.execute();
System.out.println("执行结果:");
System.out.println(printBytes(commandResult.getOutput()));
System.out.println("异常信息:");
System.out.println(printBytes(commandResult.getError()));
System.out.println("退出值:");
System.out.println(commandResult.getExitCode());
}
private static String printBytes(byte[] bytes) {
try {
return new String(bytes, "GBK");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return "GBK编码异常";
}
}