执行shell命令的两种方式
方式一:ProcessBuilder
优点:可以设置进程属性;
缺点:传入命令的方式不够人性化(个人习惯);
ProcessBuilder pb=new ProcessBuilder("ps","-ef");
pb.start();
方式二:Runtime
优点:使用起来方便,直接传入命令串即可;
缺点:无法设置进程属性;
Runtime.getRuntime().exec(cmd)
存在问题及解决方案
问题:两种方式都存在一个问题,当命令中存在管道或者重定向时执行会出错;
解决方案:对于Linux,把整个命令都当成sh的参数传入,用sh来执行命令:
List<String> cmds = new ArrayList<String>();
cmds.add("sh");
cmds.add("-c");
cmds.add("ps -ef | grep -v grep");
ProcessBuilder=new ProcessBuilder(cmds);
Process p = pb.start();
对于Windows,把sh换成cmd.exe就行了。
使用示例
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.apache.commons.lang.StringUtils;
public class ProcessBuilderTest {
/**
* 功能:执行外部命令
* @param cmd待执行的命令
* @return 执行结果
*/
public static String test(String cmd) throws Exception {
if (StringUtils.isEmpty(cmd)) {
return null;
}
//使用"sh -c 命令字符串"的方式解决管道和重定向的问题
List<String> cmds = new LinkedList<String>();
cmds.add("sh");
cmds.add("-c");
cmds.add(cmd);
ProcessBuilder pb = new ProcessBuilder(cmds);
//重定向到标准输出
pb.redirectErrorStream(true);
Process p = pb.start();
p.waitFor(3, TimeUnit.SECONDS);
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
StringBuffer sb = new StringBuffer();
String line;
while ((line = br.readLine()) != null) {
sb.append(line).append("\n");
}
String result = sb.toString();
return result;
}
public static void main(String[] args){
try {
ProcessBuilderTest.test("ps -ef | grep java | grep -v grep");
} catch (Exception e) {
e.printStackTrace();
}
}
}