杰瑞科技汇

Java 如何执行 Linux 命令?

在Java中执行Linux命令

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

Java 如何执行 Linux 命令?-图1
(图片来源网络,侵删)

使用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();
        }
    }
}

注意事项

  1. 处理输入输出流:必须及时读取命令的输出流和错误流,否则可能导致进程阻塞
  2. 命令拼接安全:避免直接拼接用户输入到命令中,防止命令注入攻击
  3. 超时处理:长时间运行的命令应该设置超时
  4. 路径处理:使用绝对路径或正确设置工作目录
  5. 异常处理:妥善处理各种可能的异常情况

更健壮的实现示例

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就足够了;对于复杂场景,第三方库可能更合适。

Java 如何执行 Linux 命令?-图2
(图片来源网络,侵删)
Java 如何执行 Linux 命令?-图3
(图片来源网络,侵删)
分享:
扫描分享到社交APP
上一篇
下一篇