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

如何在Java中通过Process对象在已启动的Shell内执行命令

问题:Java启动Docker容器内Bash后无法获取命令输出

问题场景

我通过Java代码启动了一个连接到RabbitMQ Docker容器的Bash Shell:

Process process = Runtime.getRuntime().exec("docker exec rabbitmq bash");

接着尝试在这个Shell里执行rabbitmqctl list_queues命令:

Writer w = new OutputStreamWriter(process.getOutputStream(), "UTF-8");
w.write("rabbitmqctl list_queues\n");
w.flush();

但用以下代码无法获取该命令的输出:

BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
    System.out.println(line);
}

程序没有报错,但如果输入格式错误的命令,能通过错误流收到提示信息:

BufferedReader error = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String errorString = error.readLine();
System.out.println("\nError : " + errorString);

int exitCode = process.waitFor();

原因分析

  • 交互式Shell特性:docker exec rabbitmq bash启动的是交互式Bash,默认会等待用户输入,非交互式场景下不会主动处理输入并输出结果。
  • 输出缓冲问题:非交互式模式下Bash会启用行缓冲或块缓冲,输出不会立即刷新到标准输出流,导致读取代码一直阻塞等待。
  • Shell未退出:执行完命令后Bash仍在运行等待下一条指令,输出流不会关闭,读取操作无法结束。

解决方案

方案1:直接执行目标命令(推荐)

跳过启动Bash的步骤,直接通过docker exec执行rabbitmqctl命令,直接获取输出:

Process process = Runtime.getRuntime().exec("docker exec rabbitmq rabbitmqctl list_queues");

// 读取标准输出
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
    System.out.println(line);
}

// 读取错误输出
BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String errorLine;
while ((errorLine = errorReader.readLine()) != null) {
    System.err.println("Error: " + errorLine);
}

int exitCode = process.waitFor();
System.out.println("Exit code: " + exitCode);

方案2:通过Bash执行(需调整)

让Bash执行完命令后立即退出,同时关闭输出缓冲:

Process process = Runtime.getRuntime().exec("docker exec rabbitmq bash -c 'rabbitmqctl list_queues'");

// 读取输出和错误流的代码同上

或者通过输入流传递命令时,加上退出指令并强制关闭缓冲:

Process process = Runtime.getRuntime().exec("docker exec rabbitmq bash");
Writer w = new OutputStreamWriter(process.getOutputStream(), "UTF-8");
// 用stdbuf关闭输出缓冲,执行命令后退出Shell
w.write("stdbuf -o0 rabbitmqctl list_queues\n");
w.write("exit\n");
w.flush();
w.close(); // 关闭输入流,告知Shell无更多输入

// 读取标准输出
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
    System.out.println(line);
}

// 读取错误输出
BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String errorLine;
while ((errorLine = errorReader.readLine()) != null) {
    System.err.println("Error: " + errorLine);
}

int exitCode = process.waitFor();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 06:37:08