Derek Derek - 11 months ago 75
Java Question

Problem with calling rsync+ssh from java on windows

I'm having trouble calling rsync from java on windows vista with cygwin installed.
Its strange as pasting the exact same command into a command shell works fine.

My test java call looks like this.

String[] envVars = {"PATH=c:/cygwin/bin;%PATH%"};
File workingDir = new File("c:/cygwin/bin/");
Process p = Runtime.getRuntime().exec("c:/cygwin/bin/rsync.exe -verbose -r -t -v --progress -e ssh /cygdrive/c/Users/dokeeffe/workspace/jrsync/",envVars,workingDir);

Then I start 2 stream reader threads to capture and log the inputStream and errorStream of the Process p.

Here is the output....

DEBUG: com.mddc.client.rsync.StreamGobbler - opening connection using: ssh rsync --server -vvtre.iLs . /home/dokeeffe/rsync/
DEBUG: com.mddc.client.rsync.StreamGobbler - rsync: pipe: Operation not permitted (1)
DEBUG: com.mddc.client.rsync.StreamGobbler - rsync error: error in IPC code (code 14) at /home/lapo/packaging/rsync-3.0.4-1/src/rsync-3.0.4/pipe.c(57) [sender=3.0.4]

The rsync code where the error happens is pipe.c(57) which is this.

if (fd_pair(to_child_pipe) < 0 || fd_pair(from_child_pipe) < 0) {
rsyserr(FERROR, errno, "pipe");

So, for some reason fd_pair(to_child_pipe) is < 0 or fd_pair(from_child_pipe) < 0.

If anyone has any suggestions it would be great as I'm stuck now.

Answer Source

Does cygwin's binary distribution of rsync recognize the ssh command? The command you are trying to execute probably works fine when you put into the shell because something like bash knows how to interpret the ssh command to establish a connection, i.e. use the ssh program to create a connection for the rsync program. From your debugging information I think rsync is expecting a connection but instead receives a string "ssh ..." which it fails to pipe.

To get around this you have to let bash do the work for you. Look at this page in the section on threads to tend the child. You would need to fork an instance of a command shell and write your command to the shell subprocess. So something like this:

Process p = Runtime.getRuntime().exec("c:/cygwin/bin/bash.exe");
OutputStreamWriter osw = new OutputStreamWriter(p.getOutputStream());
BufferedWriter bw = new BufferedWriter( osw, 100);
}catch(IOExeception e){
    System.out.println("Problem writing command.");

You would probably want to read the processes output too because it will stop executing if you do not read it. The link provided covers the topic well.