在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执行多条命令,并根据需求选择最适合的实现方式。