Search code examples
javamysqlprocessbuilder

process builder causes error2 cannot find path specified even though the command runs from cmd


I am using ProcessBuilder to execute a mysqldump from java code and this is my code

    public static void executeCommant(String... command) throws Exception {
        ProcessBuilder processBuilder = null;
        processBuilder = new ProcessBuilder(command);

        processBuilder.redirectErrorStream(true);
        Process process = processBuilder.start();

        int resultCode = process.waitFor();

        if (resultCode != 0) {
            throw new Exception("" + readCommandOutput(process.getInputStream()));
        }
    }
private static String readCommandOutput(InputStream inputStream) throws IOException {
        StringBuilder sb = new StringBuilder();
        BufferedReader br = null;
        try {
            br = new BufferedReader(new InputStreamReader(inputStream));
            String line = null;
            while ((line = br.readLine()) != null) {
                sb.append(line + System.getProperty("line.separator"));
            }
        } finally {
            br.close();
        }
        return sb.toString();
    }

public static void main(String[] args) throws Exception {

        executeCommant("mysqldump -u root -P 3316 -h localhost > G:\\test.sql");

    }

Problem is i get the following exception even though when i run the same command from cmd i dont get any problem, and i just cannot figure out why it cannot find the specified file!! PS: i tried with giving the full path for the mysqldump.exe and got the same result

Exception in thread "main" java.io.IOException: Cannot run program "mysqldump -u root -P 3316 -h localhost > G:\test.sql": CreateProcess error=2, The system cannot find the file specified
    at java.lang.ProcessBuilder.start(ProcessBuilder.java:470)
    at com.etq.e2mc.platform.windows.WindowsProcess.executeCommant(WindowsProcess.java:46)
    at com.etq.e2mc.platform.windows.WindowsProcess.main(WindowsProcess.java:67)
Caused by: java.io.IOException: CreateProcess error=2, The system cannot find the file specified
    at java.lang.ProcessImpl.create(Native Method)
    at java.lang.ProcessImpl.<init>(ProcessImpl.java:177)
    at java.lang.ProcessImpl.start(ProcessImpl.java:28)
    at java.lang.ProcessBuilder.start(ProcessBuilder.java:452)
    ... 2 more

Solution

  • First, your are calling the ProcessBuilder(String... command) with an array, meaning that the first value of the array is the program. However, you are sending the entire string "mysqldump -u root -P 3316 -h localhost > G:\\test.sql", and that is not a program. Only mysqldump is the program.

    Second, when capturing output using getInputStream(), you need to do that before calling waitFor(), otherwise your risk the output buffer running full, halting execution of the program you're running, essentially causing a deadlock between your program waiting for the command to exit and the command waiting for you to read the output. If you need the stream, you generally need to read it in a separate thread.

    Third, you can't redirect output using > in the command string. That is something cmd.exe does, and you're not invoking cmd.exe. Since you want to redirect to a file, do that directly using the ProcessBuilder.

    ProcessBuilder processBuilder = new ProcessBuilder(
            "mysqldump", "-u", "root", "-P", "3316", "-h", "localhost");
    processBuilder.redirectErrorStream(true);
    processBuilder.redirectOutput(new File("G:\\test.sql"));
    Process process = processBuilder.start();
    int resultCode = process.waitFor();
    if (resultCode != 0) {
        throw new Exception("Program failed with error " + resultCode);
    }