Stack Exchange
Fail to execute mysql command to restore dump with Apache Commons Exec
My goal is to restore a Mysql dump using mysql command.
I'm having a clear difference of behaviour between a code using ProcessBuilder and Apache Commons Exec (1.3).
This code works perfectly fine
List<String> params = new ArrayList<>();
params.add("sh");
params.add("-c");
params.add("mysql -uroot -proot < /tmp/the_dump.sql");

ProcessBuilder pb = new ProcessBuilder(params);
Process p = pb.redirectErrorStream(true).start();
int exitValue = p.waitFor();

But this one (with Apache Commons Exec)
CommandLine cmdLine = new CommandLine("/usr/bin/sh");
cmdLine.addArgument("-c");
cmdLine.addArgument("mysql -uroot -proot -e 'source /tmp/the_dump.sql'");

PumpStreamHandler streamHandler = new PumpStreamHandler(System.out, System.err, System.in);
Executor executor = new DefaultExecutor();
executor.setStreamHandler(streamHandler);
int exitValue = executor.execute(cmdLine);

crashed with the following error :

Note the missing ' at the end of the command as interpreted by Apache Commons Exec.

Does anyboday has an idea how to make it work with Apache Commons Exec ?
Thanks a lot for your help,
Sylvain

The sh shell is interpreting mysql -uroot -proot -e 'source /tmp/the_dump.sql' as a single file and trying to find that file to execute. You need to pass the command to sh by writing to its input stream.
The sh shell usually accepts commands from the stdin stream. If you launch sh in a terminal window the keyboard is stdin. In this case, you're starting a subprocess, so Java has access to the input and output streams of the subprocess. In Java you can write your command to sh's stream by doing the following:
CommandLine cmdLine = new CommandLine("/usr/bin/sh");
byte[] buf = "mysql -uroot -proot -e 'source /tmp/the_dump.sql'".getBytes();
ByteArrayInputStream is = new ByteArrayInputStream(buf);
PumpStreamHandler streamHandler = new PumpStreamHandler(System.out, System.err, is);
Executor executor = new DefaultExecutor();
executor.setStreamHandler(streamHandler);
int exitValue = executor.execute(cmdLine);

Note that by using System.out and System.err in your PumpStreamHandler, you will be handling the output and error streams of the java process, not the sh subprocess.

Thanks for the tip, I'll try it as soon as possible. In any case, I also have to deal with user entry to give the user password so it will be difficult to handle both inputs !
So, I opted for a solution using a shell file accepting some arguments. Much more simple to handle.
