Java 代码执行本地命令
by emanjusaka from https://www.emanjusaka.top/2024/03/java-exec-local-command 彼岸花开可奈何
本文欢迎分享与聚合,全文转载请留下原文地址。
我们可以在命令行中执行各种命令,比如,创建文件、查看文件夹下文件、调用第三方工具等等。
如果想在 java 代码中执行命令应该怎么操作呢?我们有两种方式可以实现:
- 通过Runtime.getRuntime().exec调用命令
- 使用ProcessBuilder类来构建和执行命令
Runtime.getRuntime().exec
Runtime.getRuntime().exec()是Java中用于执行操作系统命令的方法。它允许你在Java程序中执行外部命令,并获取命令的输出和错误信息。
下面是使用Runtime.getRuntime().exec()执行一个简单命令的步骤:
- 创建一个Runtime对象,通过调用Runtime.getRuntime()方法获取。
- 调用exec()方法,传入要执行的命令和参数。
- exec()方法返回一个Process对象,表示正在执行的进程。
- 使用Process对象的方法来获取输出、错误流和返回值。
/**
* 执行本地命令
* 不支持管道和重定向机制
*
* @param command 命令
*/
public static void executeLocalCommand(String command) {
try {
// 执行命令
Process process = Runtime.getRuntime().exec(command);
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {
String line;
while ((line = reader.readLine()) != null) {
log.info(command + ",命令执行结果:", line);
}
while ((line = errorReader.readLine()) != null) {
// 输出标准错误(stderr),标记为错误信息
if (line.startsWith("[ERROR]")) {
log.error(command + ",命令执行错误:", line);
} else {
log.warn(command + ",[WARNING]" + line);
}
}
// 等待命令执行完成
int exitCode = process.waitFor();
if (exitCode != 0) {
throw new ServiceException("执行命令失败!");
}
}
} catch (IOException | InterruptedException e) {
Thread.currentThread().interrupt(); // 如果是InterruptedException,则重新设置中断状态
throw new RuntimeException(e);
}
log.info(command + ",命令执行成功");
}
注意:该方法不支持shell的管道符和重定向机制。它只能分步执行命令,每个命令都是独立的进程。
在进程执行完成后,你应该调用Process对象的waitFor()方法来等待进程结束,并获取进程的返回值。这样可以确保进程正常结束,并且你可以根据返回值进行进一步处理。
如果需要使用管道符和重定向机制,可以考虑使用ProcessBuilder类来构建和执行命令。
ProcessBuilder
ProcessBuilder是Java中用于创建和控制操作系统进程的类。它比Runtime.exec()更加强大,因为它可以处理命令行参数、错误流和输入流,并支持管道和重定向。
下面是使用ProcessBuilder执行一个简单命令的步骤:
- 创建一个ProcessBuilder对象,并传入要执行的命令和参数。
- 调用start()方法启动进程。
- 使用Process对象的方法来获取输出、错误流和返回值。
下面是一个调用的示例:
package top.emanjusaka;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
String[] command = {
"ls",
"-l"
};
// 创建ProcessBuilder对象,并传入要执行的命令和参数
ProcessBuilder processBuilder = new ProcessBuilder(command);
// 启动进程
Process process = null;
try {
process = processBuilder.start();
// 获取输出流
try (
BufferedReader outputReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));) {
String line;
while ((line = outputReader.readLine()) != null) {
System.out.println(line);
}
while ((line = errorReader.readLine()) != null) {
// 输出标准错误(stderr),标记为错误信息
if (line.startsWith("[ERROR]")) {
System.out.println(command + ",命令执行错误:" + line);
} else {
System.out.println(command + ",[WARNING]" + line);
}
}
// 等待进程执行完成,并获取返回值
int exitCode = process.waitFor();
System.out.println("Exit code: " + exitCode);
} catch (IOException e) {
throw new RuntimeException(e);
}
} catch (InterruptedException | IOException e) {
throw new RuntimeException(e);
}
}
}
执行结果:
上述代码将执行ls -l命令,并将输出打印到控制台。你可以根据需要修改命令和参数来执行其他命令或传递不同的参数。
请注意,使用ProcessBuilder时需要注意以下几点:
- ProcessBuilder可以处理命令行参数,因此你可以通过将参数作为字符串数组传递给ProcessBuilder的构造函数来传递多个参数。
- 你可以使用redirectErrorStream(true)方法将错误流合并到输出流中,这样你就可以同时读取标准输出和错误输出。
- 在进程执行完成后,你应该调用Process对象的waitFor()方法来等待进程结束,并获取进程的返回值。这样可以确保进程正常结束,并且你可以根据返回值进行进一步处理。
本文原创,才疏学浅,如有纰漏,欢迎指正。如果本文对您有所帮助,欢迎点赞,并期待您的反馈交流,共同成长。
原文地址: https://www.emanjusaka.top/2024/03/java-exec-local-command
微信公众号:emanjusaka的编程栈