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

Java升级后Runtime.exec执行mysqldump触发IOException权限问题

Java 17执行mysqldump报错权限拒绝(Error 13)排查方案

以下是一段调用mysqldump备份MySQL数据库的Java代码,在Java 8环境下运行正常,但在同一Ubuntu系统的Liberica JDK 17环境中执行失败,抛出IOException(错误码13,权限拒绝)。运行Java进程的用户已拥有mysqldump的执行权限,目标备份目录也归该用户所有。

String osName = System.getProperty("os.name").toLowerCase();
String path = "";
String backupFilePath = backupDir + System.getProperty("file.separator") + "jlawyerdb-dump.sql";

if (osName.contains("win")) {

} else if (osName.contains("linux")) {
    path="/usr/bin/";
} else if (osName.startsWith("mac")) {
    path = "/usr/local/mysql/bin/";
}

log.info("MySQL Dump: " + path + "mysqldump");

String[] cmd = null;
if ("".equals(password) || password == null) {
    cmd = new String[]{
        path + "mysqldump",
        "-P",
        port,
        "-u" + user,
        "-r",
        backupFilePath,
        "jlawyerdb"
    };
} else {
    cmd = new String[]{
        path + "mysqldump",
        "-P",
        port,
        "-u" + user,
        "-p" + password,
        "-r",
        backupFilePath,
        "jlawyerdb"
    };
}

Runtime shell = Runtime.getRuntime();
Process process = null;

File f = new File(backupFilePath);
int exitCode = 0;
try {

    if (f.exists()) {
        f.delete();
    }

    process = shell.exec(cmd);
    exitCode = process.waitFor();

    f.setLastModified(System.currentTimeMillis());

} catch (Exception ex) {
    log.error(ex);

}

测试更新

将代码提取为极简主类测试后,Shell输出如下,对比Java 8和Java 17的运行表现:

root@j-lawyer-box:/usr/local/j-lawyer-server# java -version
openjdk version "1.8.0_352"
OpenJDK Runtime Environment (build 1.8.0_352-8u352-ga-1~22.04-b08)
OpenJDK 64-Bit Server VM (build 25.352-b08, mixed mode)

root@j-lawyer-box:/usr/local/j-lawyer-server# java DumpTest 
MySQL Dump: /usr/bin/mysqldump

root@j-lawyer-box:/usr/local/j-lawyer-server# ./jre/bin/java -version
openjdk version "17.0.9" 2023-10-17 LTS
OpenJDK Runtime Environment (build 17.0.9+11-LTS)
OpenJDK 64-Bit Server VM (build 17.0.9+11-LTS, mixed mode, sharing)

root@j-lawyer-box:/usr/local/j-lawyer-server# ./jre/bin/java DumpTest 
MySQL Dump: /usr/bin/mysqldump
java.io.IOException: Cannot run program "/usr/bin/mysqldump": error=13, Keine Berechtigung
        at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1143)
        at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1073)
        at java.base/java.lang.Runtime.exec(Runtime.java:594)
        at java.base/java.lang.Runtime.exec(Runtime.java:453)
        at DumpTest.main(DumpTest.java:58)
Caused by: java.io.IOException: error=13, Keine Berechtigung
        at java.base/java.lang.ProcessImpl.forkAndExec(Native Method)
        at java.base/java.lang.ProcessImpl.<init>(ProcessImpl.java:314)
        at java.base/java.lang.ProcessImpl.start(ProcessImpl.java:244)
        at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1110)
        ... 4 more

传递给Runtime.exec的cmd数组参数如下:

/usr/bin/mysqldump
-P
3306
-uroot
-psecretvalue
-r
/usr/local/j-lawyer-server/backups/jlawyerdb-dump.sql
jlawyerdb

解决建议

  • 检查JDK安全限制:Java 17对外部进程执行的权限管控更严格,可尝试添加VM参数--permit-illegal-access临时测试,或调整JDK安装目录下conf/security/java.security中的相关配置项。
  • 替换为ProcessBuilder执行:Runtime.exec在高版本Java中已不推荐,改用ProcessBuilder可更灵活控制执行环境,示例代码:
    ProcessBuilder pb = new ProcessBuilder(cmd);
    // 继承当前进程的环境变量
    pb.environment().putAll(System.getenv());
    // 指定mysqldump所在目录为工作目录
    pb.directory(new File("/usr/bin"));
    Process process = pb.start();
    int exitCode = process.waitFor();
    
  • 排查系统安全模块限制:Ubuntu下的AppArmor或SELinux可能阻止Java 17进程调用mysqldump,可通过journalctl -xe查看系统审计日志,或临时关闭AppArmor测试(sudo aa-disable /usr/bin/mysqldump)。
  • 验证JDK自身权限:检查Liberica JDK安装目录及java二进制文件的权限,确保运行用户拥有读取和执行权限。
  • 优化mysqldump参数传递:避免直接在-p后拼接密码(部分高版本MySQL会禁用此方式),改用--defaults-extra-file指定包含密码的配置文件,示例:
    1. 创建配置文件~/.my.cnf,内容:
      [mysqldump]
      user=root
      password=secretvalue
      port=3306
      
    2. 修改cmd数组:
      cmd = new String[]{
          path + "mysqldump",
          "--defaults-extra-file=" + System.getProperty("user.home") + "/.my.cnf",
          "-r",
          backupFilePath,
          "jlawyerdb"
      };
      

内容的提问来源于stack exchange,提问作者j-dimension

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 13:27:51