ProcessBuilder 启动外部进程
ProcessBuilder 是 Java 中用于创建操作系统进程的类,相比旧版的 Runtime.exec(),它提供了更灵活和强大的控制能力。

基本用法
创建并启动简单进程
import java.io.*;
public class ProcessBuilderExample {
public static void main(String[] args) throws IOException {
// 创建 ProcessBuilder 实例
ProcessBuilder pb = new ProcessBuilder("ls", "-la");
// 启动进程
Process process = pb.start();
// 读取输出
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
}
核心功能
设置工作目录
ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "dir");
// 设置工作目录
pb.directory(new File("C:/Users/YourName"));
环境变量管理
ProcessBuilder pb = new ProcessBuilder("printenv");
Map<String, String> env = pb.environment();
// 添加/修改环境变量
env.put("MY_VAR", "custom_value");
env.put("PATH", env.get("PATH") + ":/custom/path");
// 清除所有环境变量
env.clear();
重定向输入输出
ProcessBuilder pb = new ProcessBuilder("grep", "error");
// 从文件读取输入
pb.redirectInput(new File("input.log"));
// 输出到文件
pb.redirectOutput(new File("output.txt"));
// 错误输出合并到标准输出
pb.redirectErrorStream(true);
// 或者单独重定向错误输出
pb.redirectError(new File("error.log"));
完整示例
执行复杂命令并处理输出
import java.io.*;
import java.util.concurrent.TimeUnit;
public class ProcessBuilderDemo {
public static void main(String[] args) {
try {
// 创建命令列表(Windows 示例)
ProcessBuilder pb = new ProcessBuilder(
"cmd.exe",
"/c",
"ping -n 3 8.8.8.8"
);
// 配置进程
pb.directory(new File("C:/temp"));
pb.redirectErrorStream(true);
// 启动进程
Process process = pb.start();
// 读取输出
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println("OUTPUT: " + line);
}
}
// 等待进程完成(带超时)
boolean finished = process.waitFor(30, TimeUnit.SECONDS);
if (finished) {
int exitCode = process.exitValue();
System.out.println("进程退出码: " + exitCode);
} else {
System.out.println("进程超时,强制终止");
process.destroyForcibly();
}
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
}
高级用法
使用管道(Pipe)
import java.util.List;
public class PipeExample {
public static void main(String[] args) throws IOException {
// 创建两个进程
ProcessBuilder pb1 = new ProcessBuilder("ls", "-la");
ProcessBuilder pb2 = new ProcessBuilder("grep", "java");
// 启动第一个进程
Process process1 = pb1.start();
// 将第一个进程的输出作为第二个进程的输入
Process process2 = pb2.start();
// 连接管道
try (InputStream is = process1.getInputStream();
OutputStream os = process2.getOutputStream()) {
byte[] buffer = new byte[1024];
int length;
while ((length = is.read(buffer)) != -1) {
os.write(buffer, 0, length);
}
}
// 读取最终结果
BufferedReader reader = new BufferedReader(
new InputStreamReader(process2.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
}
常见平台命令示例
public class PlatformSpecific {
// Linux/Mac 命令
public static void unixCommands() throws IOException {
// 列出目录
new ProcessBuilder("ls", "-la", "/tmp").start();
// 执行脚本
new ProcessBuilder("bash", "-c", "echo 'Hello'").start();
// 查看进程
new ProcessBuilder("ps", "-ef").start();
}
// Windows 命令
public static void windowsCommands() throws IOException {
// 列出目录
new ProcessBuilder("cmd", "/c", "dir").start();
// 查看进程
new ProcessBuilder("tasklist").start();
// IP 配置
new ProcessBuilder("ipconfig", "/all").start();
}
}
错误处理最佳实践
public class RobustProcessBuilder {
public static void executeCommand(List<String> command) {
Process process = null;
try {
ProcessBuilder pb = new ProcessBuilder(command);
pb.redirectErrorStream(true);
process = pb.start();
// 启动读取线程防止缓冲阻塞
Thread outputReader = new Thread(() -> {
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
});
outputReader.start();
// 等待完成
if (!process.waitFor(10, TimeUnit.SECONDS)) {
process.destroyForcibly();
throw new RuntimeException("进程超时");
}
int exitCode = process.exitValue();
if (exitCode != 0) {
throw new RuntimeException("进程返回非零退出码: " + exitCode);
}
} catch (IOException | InterruptedException e) {
throw new RuntimeException("执行命令失败: " + command, e);
} finally {
if (process != null) {
process.destroy();
}
}
}
}
关键注意事项
- 线程安全: Process 不是线程安全的,要考虑并发访问
- 资源释放: 始终关闭 InputStream/OutputStream
- 阻塞问题: 大输出可能导致进程阻塞,使用独立线程读取
- 跨平台: 注意命令在不同操作系统上的差异
- 安全: 避免命令注入,使用参数列表而非字符串拼接
ProcessBuilder 为 Java 提供了强大且可靠的外部进程管理能力,合理使用可以很好地扩展应用的功能边界。
版权声明:足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播