JDK自带的两种方式有通过Runtime.getRuntime().exec()和ProcessBuilder类来做, 后者是JDK1.5以后引入的,官方也建议放弃使用Runtime的方式来做。今天在实现的时候就是采用ProcessBuilder,apache commons类库也提供了一个exec包专门做这类功能,这次暂时没用到。
在编写过程中,遇到几个比较坑的地方:
1、构建ProcessBuilder采用的参数:
建议采用“/bin/bash”. "-c", "your shell"组装一个List, 其实你一次如果执行多个命令,都可以统一放到那个“your shell”字符串中。
2、执行过程中输出流控制:
在执行过程中,我们肯定需要得到正常的执行结果,也需要知道出错的内容提示, 这时需要将错误输出流重定向到标准输出流,相当于合并在一起输出
3、有些命令是需要环境变量的支持, 这时需要执行evivonment()拷贝系统相关env变量到当前进程上下文中,供命令使用。
4、如果执行过程卡死,需要知道可以kill哪个进程, 所以输出内容中将当前进程ID打印出,便于手动处理。
完整代码如下:
public int exeCmd(String shell) throws IOException { int success = 0; StringBuffer sb = new StringBuffer(); BufferedReader br = null; // get name representing the running Java virtual machine. String name = ManagementFactory.getRuntimeMXBean().getName(); String pid = name.split("@")[0]; try { System.out.println("Starting to exec{ " + shell + " }. PID is: " + pid); Process process = null; ProcessBuilder pb = new ProcessBuilder("/bin/bash", "-c", shell); pb.environment(); pb.redirectErrorStream(true); // merge error stream into standard stream process = pb.start(); if (process != null) { br = new BufferedReader( new InputStreamReader(process.getInputStream()), 1024); process.waitFor(); } else { System.out.println("There is no PID found."); } sb.append("Ending exec right now, the result is:\n"); String line = null; while (br != null && (line = br.readLine()) != null) { sb.append(line).append("\n"); } } catch (Exception ioe) { sb.append("Error occured when exec cmd:\n").append(ioe.getMessage()) .append("\n"); } finally { PrintWriter writer = null; if (br != null) { br.close(); } try { writer = new PrintWriter(System.out); writer.write(sb.toString()); } catch (Exception e) { LOG.error(e.getMessage(), e); } finally { writer.close(); } success = 1; } return success; }
时间: 2024-10-04 15:56:50