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

Java调用Shell命令获取Docker中MySQL输出失败原因排查

问题分析与修复方案

你的Java代码存在三个核心问题,导致无法获取预期输出:


1. inheritIO() 导致无法读取子进程输出

ProcessBuilder.inheritIO()会将子进程的标准输入、输出、错误流直接绑定到当前JVM的控制台流,这意味着子进程的输出会直接打印到控制台,而不会流入process.getInputStream()中。你后续读取这个流时,自然获取不到任何内容,最终rst为空字符串。

2. 缺少MySQL登录用户名参数

你在控制台执行的命令明确指定了-uroot登录用户,但Java代码中的命令仅包含-p123456,未指定用户名。MySQL客户端默认会使用当前操作系统用户名尝试登录,而Docker容器内的MySQL大概率没有对应用户,导致登录失败,没有输出内容。

3. 未处理错误流

即使登录失败,错误信息会输出到标准错误流,但原代码既用inheritIO()接管了流,又未读取错误流,导致你无法看到登录失败的提示信息,难以排查问题。


修复后的代码

修正执行命令的方法

private Pair<Integer, String> execForExitCode(String[] command) {
    try {
        Process process = new ProcessBuilder(command).start();
        // 读取标准输出
        String stdout = new String(process.getInputStream().readAllBytes(), StandardCharsets.UTF_8);
        // 读取错误输出,用于排查问题
        String stderr = new String(process.getErrorStream().readAllBytes(), StandardCharsets.UTF_8);
        int exitCode = process.waitFor();
        // 合并输出与错误信息,方便调试
        String rst = stdout.trim() + (!stderr.isEmpty() ? "\n错误信息:" + stderr.trim() : "");
        return Pair.of(exitCode, rst);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

修正命令数组(添加用户名参数)

String[] cmd = new String[] {"docker", "exec", "my", "mysql", "-uroot", "-p123456", "-e", "select @@report_host\\G"};
Pair<Integer, String> result = this.execForExitCode(cmd);
String[] lines = result.getRight().split("\n");
log.info("getDbReportHost:");
for (String line : lines) {
    log.info(line);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 15:14:55