在Java中执行Linux命令
在Java中执行Linux命令有几种常见方法,以下是几种主要实现方式:

使用Runtime.exec()
这是最基础的方法,但使用时需要小心处理输入输出流:
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class ExecuteCommand {
public static void main(String[] args) {
try {
// 执行命令
Process process = Runtime.getRuntime().exec("ls -l");
// 读取命令输出
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 (Exception e) {
e.printStackTrace();
}
}
}
使用ProcessBuilder(推荐)
ProcessBuilder提供了更灵活的控制方式:
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
public class ProcessBuilderExample {
public static void main(String[] args) {
try {
// 创建ProcessBuilder
ProcessBuilder pb = new ProcessBuilder("ls", "-l");
// 设置工作目录(可选)
pb.directory(new File("/path/to/directory"));
// 启动进程
Process process = pb.start();
// 读取输出
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 (Exception e) {
e.printStackTrace();
}
}
}
使用第三方库
对于更复杂的命令执行需求,可以考虑使用第三方库:
Apache Commons Exec
import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecutor;
import org.apache.commons.exec.PumpStreamHandler;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
public class CommonsExecExample {
public static void main(String[] args) {
CommandLine cmdLine = CommandLine.parse("ls -l");
DefaultExecutor executor = new DefaultExecutor();
// 捕获输出
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
PumpStreamHandler streamHandler = new PumpStreamHandler(outputStream);
executor.setStreamHandler(streamHandler);
try {
int exitCode = executor.execute(cmdLine);
System.out.println("Exit code: " + exitCode);
System.out.println("Output:\n" + outputStream.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
}
使用Guava的ProcessFunction
import com.google.common.collect.Lists;
import com.google.common.io.ByteStreams;
import java.io.IOException;
import java.util.List;
public class GuavaProcessExample {
public static void main(String[] args) {
List<String> command = Lists.newArrayList("ls", "-l");
try {
Process process = new ProcessBuilder(command).start();
String output = new String(ByteStreams.toByteArray(process.getInputStream()));
System.out.println(output);
int exitCode = process.waitFor();
System.out.println("Exit code: " + exitCode);
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
}
注意事项
- 处理输入输出流:必须及时读取命令的输出流和错误流,否则可能导致进程阻塞
- 命令拼接安全:避免直接拼接用户输入到命令中,防止命令注入攻击
- 超时处理:长时间运行的命令应该设置超时
- 路径处理:使用绝对路径或正确设置工作目录
- 异常处理:妥善处理各种可能的异常情况
更健壮的实现示例
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class RobustCommandExecutor {
public static void executeCommand(String[] command, long timeout) {
Process process = null;
try {
process = new ProcessBuilder(command).start();
// 读取输出
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();
}
}).start();
// 读取错误
new Thread(() -> {
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getErrorStream()))) {
String line;
while ((line = reader.readLine()) != null) {
System.err.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}).start();
// 等待进程结束或超时
if (timeout > 0) {
process.waitFor(timeout, java.util.concurrent.TimeUnit.MILLISECONDS);
if (process.isAlive()) {
process.destroyForcibly();
}
} else {
process.waitFor();
}
System.out.println("Exit code: " + process.exitValue());
} catch (IOException | InterruptedException e) {
e.printStackTrace();
} finally {
if (process != null) {
process.destroy();
}
}
}
public static void main(String[] args) {
executeCommand(new String[]{"ls", "-l"}, 5000); // 5秒超时
}
}
选择哪种方法取决于你的具体需求,对于简单命令,Runtime.exec()或ProcessBuilder就足够了;对于复杂场景,第三方库可能更合适。


