You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Java执行Shell命令并在执行过程中实时打印输出内容

Java执行Shell命令并实时打印输出实现方案

要实现执行Shell命令时实时输出内容,核心是异步消费进程的输出缓冲区,不能等进程执行完成再统一读取。Java的Process类启动外部进程后,进程的标准输出、错误输出都会写入独立的缓冲区,若缓冲区满且未被消费,进程会进入阻塞状态停止运行,因此必须通过独立线程消费输出流才能拿到实时内容。

完整实现代码

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.List;

public class ShellExecutor {
    public static void main(String[] args) throws IOException, InterruptedException {
        // 按操作系统匹配命令前缀,示例执行持续ping命令
        String os = System.getProperty("os.name").toLowerCase();
        List<String> command;
        if (os.contains("win")) {
            // Windows下的ping命令配置
            command = List.of("cmd.exe", "/c", "ping -t www.baidu.com");
        } else {
            // Linux/macOS下的ping命令配置
            command = List.of("/bin/sh", "-c", "ping www.baidu.com");
        }

        // 构建进程,推荐用ProcessBuilder替代旧的Runtime.exec()
        ProcessBuilder processBuilder = new ProcessBuilder(command);
        // 可配置合并错误输出到标准输出,简化流消费逻辑,也可以单独消费错误流
        processBuilder.redirectErrorStream(true);
        Process process = processBuilder.start();

        // 启动独立线程消费输出流,实现实时打印
        new Thread(() -> {
            try (BufferedReader reader = new BufferedReader(
                    new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8))) {
                String line;
                // 逐行读取内容,读到后直接打印不需要缓存
                while ((line = reader.readLine()) != null) {
                    System.out.println("实时输出:" + line);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }).start();

        // 等待命令执行完成,0为正常退出码
        int exitCode = process.waitFor();
        System.out.println("命令执行结束,退出码:" + exitCode);
    }
}

关键注意点

  • 若需要单独处理错误输出,不要开启redirectErrorStream(true),单独再起一个线程消费process.getErrorStream()即可,避免两个流缓冲区交叉阻塞
  • 消费流时建议显式指定编码,避免不同操作系统默认编码不一致导致输出乱码
  • 若需要中途终止命令执行,直接调用process.destroy()方法即可销毁正在运行的进程
  • 如果命令参数包含空格,直接传入字符串列表构造命令即可,不要用split(" ")拆分,避免参数拆分错误

内容的提问来源于stack exchange,提问作者Anas Elgarhy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 22:15:07