最近做公司的WebLogic 迁移工作,其中很多东西需要使用到相关的shell命令操作,需要同一个shell多次执行相关命令,简单使用Java ProcessBuilder 封装了一个shell工具类,可以同时在linux/windows下运行。并且每次运行的命令都有其执行结果返回。
package com.apusic.common.util;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Scanner;
import java.util.regex.Pattern;
public final class ShellUtil implements AutoCloseable{
private static final String FLAG = "COMMANDFLAG...COMMANDFLAG";
private static final String FLAG_CMD = "echo " + FLAG;
public static final boolean isUnixLike;
private static String charset;
static {
isUnixLike = !Pattern.compile(".*windows.*", 2).matcher(System.getProperty("os.name")).find();
charset = isUnixLike ? "utf-8" : "gbk";
}
private Process process;
private Scanner scanner;
private OutputStream outputStream;
public ShellUtil(OutputStream outputStream) throws IOException {
ProcessBuilder pb = new ProcessBuilder(isUnixLike ? "/bin/bash" : "cmd");
pb.redirectErrorStream(true);
this.process = pb.start();
this.scanner = new Scanner(this.process.getInputStream(), charset);
this.outputStream = outputStream;
}
public void cd(String dir) throws IOException {
if (!isUnixLike) {
this.exec(String.format("cd /d %s",dir));
return;
}
this.exec(String.format("cd %s", dir));
}
//标志命令中间的命令才是执行的命令
public String exec(String cmd, String... args) throws IOException {
StringBuilder rst = new StringBuilder(cmd);
if (args != null) {
for(int i = 0; i < args.length; ++i) {
rst.append(" ").append(args[i]);
}
}
StringBuilder s = new StringBuilder(FLAG_CMD);
if(isUnixLike){
s.append(";");
}else{
s.append("&");
}
s.append(rst.toString());
if(isUnixLike){
s.append(";");
}else{
s.append("&");
}
s.append(FLAG_CMD);
OutputStream os = this.process.getOutputStream();
os.write(s.toString().getBytes(charset));
os.write("\n".getBytes());
os.flush();
rst.insert(0,"[").append("]").append("\n");
for(int i=0;this.scanner.hasNextLine();) {
String line = this.scanner.nextLine();
if(line.indexOf(FLAG) == 0){
i++;
if(i == 2){
break;
}
}
if(i == 1 && !line.contains(FLAG)){
rst.append(line).append('\n');
}
}
if(this.outputStream != null) this.outputStream.write(rst.toString().getBytes());
return rst.toString();
}
@Override
public void close() {
this.process.destroyForcibly();
}
}