1

我正在编写一个需要执行 mysql 转储的 java 应用程序,并且我正在使用 runtime.exec,基于when runtime.exec 不会写文章。代码如下:

public int exectuteCommand(){
    Runtime rt = Runtime.getRuntime();
    logger.debug("exexuting cmd: " + showCommand());
    int exit = -1;
    try {
        Process proc = rt.exec(cmd);

        ExtProcessStreamHandler errorHandler = new ExtProcessStreamHandler(proc.getErrorStream(), "ERROR");
        ExtProcessStreamHandler outHandler = new ExtProcessStreamHandler(proc.getInputStream(), "OUTPUT");

        // kick it off
        errorHandler.start();
        outHandler.start();
        exit = proc.waitFor();

    } catch (IOException e) {
        logger.error("ERROR!! ~~ executing command " + showCommand(), e);
        e.printStackTrace();
    } catch (InterruptedException e) {
        logger.error("ERROR!! ~~ unexpected return for " + showCommand() + " , returned " + exit, e);
        e.printStackTrace();
    }

    return exit;
}

1)进程返回的命令在shell中工作(我在mac上运行它)。我遇到的第一个错误是无法找到 mysqldump 命令。这导致此错误:

java.io.IOException: Cannot run program "mysqldump": error=2, No such file or directory

我通过将文件的完整路径添加到命令来解决这个问题。$PATH 变量显示

/usr/local/mysql/bin/mysqldump 

作为完整路径。如何确保我的 java 应用程序具有该信息?

2) 将完整路径添加到命令时,我收到此错误消息:

 INFO [Thread-1] (ExtProcessStreamHandler.java:28) - external process ERROR : mysqldump: Couldn't find table: ">"

这是构建命令数组的代码:

return new String[] {MYSQLDUMP_CMD, "-u", USER_DEFAULT, "-p"+ PW_DEFAULT, TEST_DB_NAME,
            ">", DUMP_LOC};

再次,当我将传递给 java 应用程序的命令复制到我的 mac 上的 shell 中时,它可以工作。不知道我做错了什么。提前致谢!

4

2 回答 2

1

它认为“>”是一个用于mysqldump. 您正在调用可执行文件,而不是评估 shell 表达式。如果要管道输出,请在代码中使用outHandlerand errorHandler

另一种方法是调用 shell 并将您要评估的表达式作为参数传递:

expr = new StringBuilder()
    .append(MYSQLDUMP_CMD).append(' ')
    .append("-u").append(USER_DEFAULT).append(' ')
    .append("-p").append(PW_DEFAULT).append(' ')
    .append(TEST_DB_NAME).append(' ')
    .append(">").append(' ')
    .append(DUMP_LOC)
    .toString();
return new String[] {"/bin/bash", "-c", expr};

如果您构建命令数组的代码没有将带空格的参数包含在单引号中(或者如果 JDK 没有为您执行此操作),则修改 StringBuilder 语句以为您创建带引号的引号。

于 2013-07-10T19:34:56.193 回答
0

下面的代码对我有用

public static void backup() {
        String currentDate = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy_MM_dd"));
        String backupPath = String.format("%s/%s.%s", Helper.BACKUP_PATH, currentDate, "sql");
        File backupFile = new File(backupPath);
        if (!backupFile.exists()) {
            try {
            backupFile.createNewFile();
            String mysqlCom=String.format("mysqldump -u%s -p%s %s",USER_NAME,PASSWORD,DB);
            String[] command = new String[] { "/bin/bash", "-c",mysqlCom};
            ProcessBuilder processBuilder = new ProcessBuilder(Arrays.asList(command));
            processBuilder.redirectError(Redirect.INHERIT);
            processBuilder.redirectOutput(Redirect.to(backupFile));
            Process process = processBuilder.start();
            process.waitFor();
            LOGGER.info("Backup done");
        } catch (IOException e1) {
            e1.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    } else {
        LOGGER.info("Database already backuped today");
    }
}
于 2018-04-30T12:45:51.020 回答