上一篇
Java如何调用cmd命令行?
- 电脑教程
- 2025-06-13
- 4451
在Java中调用命令行,通常使用
Runtime.getRuntime().exec()或
ProcessBuilder类执行CMD命令,通过创建Process对象获取输入/输出流,可读取命令结果并处理执行状态,需注意异常处理和资源释放。
核心方法:Runtime.exec()
Runtime.getRuntime().exec() 是Java早期提供的API,适用于简单命令调用。
基础示例
try {
// 执行dir命令(Windows)或ls命令(Linux/Mac)
Process process = Runtime.getRuntime().exec("cmd /c dir C:\");
// 获取命令输出流
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream())
);
// 读取输出内容
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
// 等待命令执行完成(阻塞当前线程)
int exitCode = process.waitFor();
System.out.println("Exit Code: " + exitCode);
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
关键参数说明
cmd /c [命令]:Windows中/c表示执行后关闭cmd窗口。- 若命令含空格(如路径),需用数组传参避免解析错误:
Process process = Runtime.getRuntime().exec( new String[]{"cmd", "/c", "echo", "Hello World!"} );
推荐方法:ProcessBuilder
ProcessBuilder(Java 5+)提供更灵活的参数控制、环境变量管理和流重定向。
基础示例
try {
// 构建命令及参数
ProcessBuilder builder = new ProcessBuilder(
"cmd.exe", "/c", "ping", "www.baidu.com"
);
// 重定向错误流到标准输出(便于统一处理)
builder.redirectErrorStream(true);
// 启动进程
Process process = builder.start();
// 读取输出
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream())
)) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
// 检查执行结果
int exitCode = process.waitFor();
if (exitCode == 0) {
System.out.println("命令执行成功!");
} else {
System.out.println("命令执行失败!Exit Code: " + exitCode);
}
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
进阶功能
- 设置工作目录:
builder.directory(new File("D:\project")); - 环境变量管理:
Map<String, String> env = builder.environment(); env.put("JAVA_HOME", "C:\Program Files\Java\jdk-17"); - 输出重定向到文件:
builder.redirectOutput(new File("output.log"));
注意事项与最佳实践
-
流处理必须完整
未读取的输出流可能导致进程阻塞,始终处理getInputStream()(标准输出)和getErrorStream()(错误输出)。
-
超时控制
使用waitFor(long timeout, TimeUnit unit)避免无限等待:if (!process.waitFor(30, TimeUnit.SECONDS)) { process.destroy(); // 强制终止进程 } -
命令注入风险
禁止直接拼接用户输入到命令中!应使用参数化传递:
// 错误示例(高危!) String userInput = "malicious_command & rm -rf /"; Runtime.getRuntime().exec("cmd /c " + userInput); // 正确做法 ProcessBuilder builder = new ProcessBuilder("cmd", "/c", "safe-command", userInput); -
跨平台兼容性
- Windows:命令前缀
cmd /c - Linux/Mac:使用
/bin/sh -c或直接调用可执行文件String command = System.getProperty("os.name").toLowerCase().contains("win") ? "cmd /c dir" : "/bin/ls";
- Windows:命令前缀
-
异常处理
捕获IOException(命令不存在)和InterruptedException(进程中断)。
Runtime与ProcessBuilder对比
| 特性 | Runtime.exec() | ProcessBuilder |
|---|---|---|
| 参数灵活性 | 需手动处理空格和引号 | 支持参数列表(更安全) |
| 环境变量控制 | 无直接支持 | 可通过environment()修改 |
| 工作目录设置 | 不支持 | 支持directory() |
| 流重定向 | 需手动编码 | 内置redirectOutput() |
| 适用场景 | 简单命令 | 复杂流程或生产环境 |
- 简单命令:优先使用
Runtime.exec(),注意参数格式。 - 复杂任务:选择
ProcessBuilder,尤其在需要环境控制、目录设置或流重定向时。 - 安全第一:严格校验外部输入,避免命令注入破绽。
通过合理选择API并遵循最佳实践,Java可高效安全地集成系统命令,适用于自动化部署、批处理等场景。
引用说明 参考Oracle官方文档:
- Runtime.exec()
- ProcessBuilder
安全实践依据OWASP命令注入防护指南。
