在Java中使用Apache Commons Exec库执行多条命令,可以通过以下几种方式实现
方法1:使用命令连接符(推荐)
通过&&
(Windows/Linux均支持)或;
(Linux)连接多条命令,一次性执行:
import org.apache.commons.exec.CommandLine; import org.apache.commons.exec.DefaultExecutor; import org.apache.commons.exec.PumpStreamHandler; import java.io.ByteArrayOutputStream; public class ExecMultipleCommands { public static void main(String[] args) throws Exception { // 组合命令(Windows示例) CommandLine cmd = new CommandLine("cmd.exe"); cmd.addArgument("/c"); // 执行后关闭 cmd.addArgument("echo First Command && mkdir test_dir && echo Done", false); // false: 禁止解析参数 // Linux/macOS示例 // CommandLine cmd = new CommandLine("/bin/sh"); // cmd.addArgument("-c"); // cmd.addArgument("echo 'First Command'; mkdir test_dir; echo 'Done'", false); // 捕获输出 ByteArrayOutputStream output = new ByteArrayOutputStream(); PumpStreamHandler streamHandler = new PumpStreamHandler(output); DefaultExecutor executor = new DefaultExecutor(); executor.setStreamHandler(streamHandler); int exitCode = executor.execute(cmd); System.out.println("Exit Code: " + exitCode); System.out.println("Output:\n" + output.toString()); } }
方法2:循环执行多条命令
单独执行每条命令,适合需要独立处理结果的场景:
import org.apache.commons.exec.CommandLine; import org.apache.commons.exec.DefaultExecutor; public class ExecLoopCommands { public static void main(String[] args) throws Exception { String[] commands = { "echo First Command", // Windows/Linux通用 "mkdir test_dir_loop", // 创建目录 "echo Done" }; for (String command : commands) { CommandLine cmd; if (System.getProperty("os.name").startsWith("Windows")) { cmd = new CommandLine("cmd.exe"); cmd.addArgument("/c"); cmd.addArgument(command, false); } else { cmd = new CommandLine("/bin/sh"); cmd.addArgument("-c"); cmd.addArgument(command, false); } int exitCode = new DefaultExecutor().execute(cmd); System.out.println("Command: " + command + " | Exit Code: " + exitCode); } } }
关键注意事项:
-
操作系统兼容性:
-
Windows:使用
cmd.exe /c "命令"
-
Linux/macOS:使用
/bin/sh -c "命令"
-
-
特殊字符处理:
-
使用
addArgument(..., false)
避免解析参数中的特殊字符 -
复杂命令建议用双引号包裹:
cmd.addArgument("\"your command\"", false)
-
-
错误处理:
-
try { executor.execute(cmd); } catch (ExecuteException e) { System.err.println("Execution failed: " + e.getMessage()); System.err.println("Exit code: " + e.getExitValue()); }
-
- 超时控制:
-
ExecuteWatchdog watchdog = new ExecuteWatchdog(5000); // 5秒超时 executor.setWatchdog(watchdog);
-
-
输出重定向:
-
使用
PumpStreamHandler
捕获输出 -
用
System.out
直接打印:executor.setStreamHandler(new PumpStreamHandler(System.out))
-
最佳实践:
-
简单命令序列 → 使用
&&
连接(方法1) -
需要独立错误处理 → 循环执行(方法2)
-
复杂脚本 → 保存为脚本文件并执行
-
跨平台 → 根据
os.name
动态选择命令前缀
常见问题解决:
问题1:命令在命令行能运行,但Java中失败
解决:显式指定shell路径(如Windows用C:\\Windows\\System32\\cmd.exe
)
问题2:空格/引号解析错误
解决:使用addArgument
单独添加参数,避免拼接字符串:
cmd.addArgument("/c"); cmd.addArgument("echo", false); cmd.addArgument("Hello World", false); // 作为独立参数传递
通过以上方法,你可以灵活地在Java中使用Commons Exec执行多条命令,并根据需求选择最适合的实现方式。