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

Java调用Runtime.exec执行docker run挂载volume失败返回125

问题根因

这个问题和权限、Docker配置没有关系,是Java Runtime.exec(String)的参数拆分逻辑存在设计坑,才导致Docker返回125退出码。
你在终端手动敲命令能正常运行,是因为bash/zsh这类shell会自动解析参数里的引号,把引号包裹的路径识别为单个参数传给Docker进程;但Runtime.exec(String)不会调用shell处理命令,它只会用最简单的空格分割规则拆分字符串,既不会识别你写的转义双引号\",也不会把引号内的内容当成整体参数。
你代码里写的带引号的-v参数,实际传到Docker时,双引号本身成了参数内容的一部分,Docker识别到挂载路径格式非法,直接就退出了。
你之前看不到任何报错也很正常:你只读取了进程的标准输出流,Docker的报错信息是写到标准错误流p.getErrorStream()里的,把这个流的内容打印出来,就能看到明确的挂载参数格式错误提示。

修复方案

两种可靠修复方式,优先选第一种:

方案1:使用数组传参重载(推荐)

不要传入整行命令字符串,直接把每个参数按顺序拆成字符串数组传入,完全绕开字符串拆分的坑,路径不需要额外加引号转义,哪怕路径里带空格也不会出问题:

public class Test {
    public static void main(String[] args) throws IOException, InterruptedException {
        // 每个参数单独作为数组元素,不需要额外加引号
        String[] cmd = {
            "docker", "run", "-d", "-it",
            "-v", "/Users/myname/Documents/MC_Servers/BungeeCord/plugins/PlayerServers/servers/OpenSourcee:/data",
            "-p", "32348:32348",
            "-e", "TYPE=PAPER",
            "-e", "ONLINE_MODE=false",
            "-e", "SERVER_PORT=32348",
            "-e", "EULA=TRUE",
            "-e", "VERSION=1.8.8",
            "--name", "OpenSourcee",
            "itzg/minecraft-server"
        };
        var p = Runtime.getRuntime().exec(cmd, null, null);

        // 同时读取标准输出和标准错误,避免流缓冲区满导致进程卡死
        var stdoutReader = new BufferedReader(new InputStreamReader(p.getInputStream()));
        var stderrReader = new BufferedReader(new InputStreamReader(p.getErrorStream()));
        String line;
        System.out.println("=== 标准输出 ===");
        while ((line = stdoutReader.readLine()) != null) {
            System.out.println(line);
        }
        System.out.println("=== 错误输出 ===");
        while ((line = stderrReader.readLine()) != null) {
            System.out.println(line);
        }

        System.out.println("进程退出码:" + p.waitFor());
    }
}

方案2:显式调用shell执行命令

如果一定要复用整行命令字符串,可以显式把命令传给系统shell执行,让shell帮你处理引号解析,逻辑和你在终端手动执行完全一致:

public class Test {
    public static void main(String[] args) throws IOException, InterruptedException {
        // 显式调用sh -c 执行完整命令字符串
        String[] cmd = {"/bin/sh", "-c", "docker run -d -it -v \"/Users/myname/Documents/MC_Servers/BungeeCord/plugins/PlayerServers/servers/OpenSourcee:/data\" -p 32348:32348 -e TYPE=PAPER -e ONLINE_MODE=false -e SERVER_PORT=32348 -e EULA=TRUE -e VERSION=1.8.8 --name OpenSourcee itzg/minecraft-server"};
        var p = Runtime.getRuntime().exec(cmd, null, null);
        // 流读取、等待退出的逻辑和方案1一致即可
    }
}
额外注意

不管用哪种方案,都要同时消费标准输出和标准错误两个流,否则当某个流的缓冲区写满(通常是4KB左右)时,进程会直接阻塞挂住,也会表现为无输出、不退出的现象,你之前遇到的无输出问题也有这个因素的影响。
macOS和Ubuntu下复现相同问题是正常的,这个坑和操作系统无关,是Java Runtime.exec的通用行为。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 17:45:40