文章目录

    • 概要
    • 使用Runtime.exec
    • 使用ProcessBuilder
    • 使用第三方工具包commons-exec.jar

概要

java执行bat或shell脚本的方式主要有三种方式
1、 使用Runtime.exec
2、 使用ProcessBuilder
3、 使用第三方的工具包commons-exec.jar

使用Runtime.exec

在 Java 中,使用 Runtime.exec() 方法执行外部可执行文件是一个常见的做法。但是,这种方法有一些限制和潜在的问题,比如它不太容易处理进程的输入/输出流。

import java.io.IOException;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;/** * 类名称: ExeRunUtil. * 类描述: 执行cmd命令 */public class ExeRunUtil{private static Log log = LogFactory.getLog(ExeRunUtil.class); /*** 执行cmd命令 * @return 执行结果 */public static boolean exec(String[] command) {Process proc;try { proc = Runtime.getRuntime().exec(command); new StreamReader(proc,proc.getInputStream(),"Output" ).start();new StreamReader(proc,proc.getErrorStream(),"Error").start();} catch (IOException ex) {log.error("IOException while trying to execute " + command,ex);return false;}int exitStatus=1;try {exitStatus = proc.waitFor();//等待操作完成 } catch (java.lang.InterruptedException ex) { log.error("InterruptedException command: " + exitStatus,ex);} if (exitStatus != 0) { log.error("Error executing command: " + exitStatus);}return (exitStatus == 0);}}import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;/** * 获取exe执行信息 * @author shandongwill * */public class StreamReader extends Thread{private final Log logger = LogFactory.getLog(getClass());private InputStream is;private String type;private Process proc;public StreamReader(Process proc,InputStream is, String type) {this.is = is;this.type = type;this.proc=proc;}public void run() {try {InputStreamReader isr = new InputStreamReader(is);BufferedReader br = new BufferedReader(isr);String line = null;while ((line = br.readLine()) != null) {if (type.equals("Error")) {logger.error("Error:" + line);proc.destroyForcibly();} else {logger.debug("Debug:" + line);}}} catch (IOException ioe) {logger.error(ioe);}} }

使用ProcessBuilder

相比于 Runtime.exec(),ProcessBuilder 提供了更强大和灵活的功能,并允许你更好地控制进程的执行。

ProcessBuilder processBuilder = new ProcessBuilder("cmd.exe", "/c", "test.bat");processBuilder.redirectErrorStream(true);Process process = processBuilder.start();int exitCode = process.waitFor();BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));String line;while ((line = reader.readLine()) != null) {System.out.println(line);}System.out.println("Exit code: " + exitCode);

使用第三方工具包commons-exec.jar

commons-exec.jar 是 Apache Commons Exec 库的一部分,它提供了一个更强大和灵活的 API 来执行外部进程。与 Java 的标准 Runtime.exec() 和 ProcessBuilder 类相比,Apache Commons Exec 提供了更多的功能和更好的错误处理。
使用 Apache Commons Exec,你可以更容易地管理进程执行,包括设置进程的工作目录、环境变量、输入/输出流重定向、超时处理等。此外,它还提供了更好的错误消息和异常处理,帮助开发者更容易地诊断问题。
要使用 commons-exec.jar,你需要将其添加到你的项目依赖中。如果你使用 Maven,你可以在 pom.xml 文件中添加以下依赖:

<dependency><groupId>org.apache.commons</groupId><artifactId>commons-exec</artifactId><version>1.3</version> </dependency>
import java.io.ByteArrayOutputStream;import java.io.IOException;import org.apache.commons.exec.CommandLine;import org.apache.commons.exec.DefaultExecutor;import org.apache.commons.exec.ExecuteException;import org.apache.commons.exec.ExecuteWatchdog;import org.apache.commons.exec.PumpStreamHandler;/** * CMD工具类 ** @author Administrator * */public class CmdUtils {/** * 执行命令 ** @param command:命令 * @return String[]数组,String[0]:返回的正常信息;String[1]:返回的警告或错误信息 * @throws ExecuteException * @throws IOException */public static String[] handle(String command) throws ExecuteException, IOException {// 接收正常结果流ByteArrayOutputStream outputStream = new ByteArrayOutputStream();// 接收异常结果流ByteArrayOutputStream errorStream = new ByteArrayOutputStream();CommandLine commandline = CommandLine.parse(command);DefaultExecutor exec = new DefaultExecutor();exec.setExitValues(null);// 设置10分钟超时ExecuteWatchdog watchdog = new ExecuteWatchdog(600 * 1000);exec.setWatchdog(watchdog);PumpStreamHandler streamHandler = new PumpStreamHandler(outputStream, errorStream);exec.setStreamHandler(streamHandler);exec.execute(commandline);// 不同操作系统注意编码,否则结果乱码String out = outputStream.toString("UTF-8");String error = errorStream.toString("UTF-8");// 返回信息String[] result = new String[2];result[0] = out;result[1] = error;return result;}}