我在安装了cygwin的windows vista上从java调用rsync时遇到问题。 奇怪的是将完全相同的命令粘贴到命令shell中工作正常。
我的测试java调用看起来像这样。
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/ www.servername.net:/home/dokeeffe/rsync/",envVars,workingDir);
然后我启动2个流读取器线程来捕获并记录Process p的inputStream和errorStream。
这是输出....
DEBUG: com.mddc.client.rsync.StreamGobbler - opening connection using: ssh www.servername.net 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]
发生错误的rsync代码是pipe.c(57)就是这个。
if (fd_pair(to_child_pipe) < 0 || fd_pair(from_child_pipe) < 0) {
rsyserr(FERROR, errno, "pipe");
exit_cleanup(RERR_IPC);
}
因此,由于某种原因,fd_pair(to_child_pipe)是&lt; 0或fd_pair(from_child_pipe)&lt; 0
如果有人有任何建议,那么现在我就会被困住。 谢谢,
答案 0 :(得分:0)
你有忘记的某个私人/公共密钥库吗?
答案 1 :(得分:0)
我从未尝试使用不同的线程进行读/写,只是执行命令的同一线程。这会导致你的问题吗?
您也可以尝试将-v传递给ssh以获取调试输出。这帮助我解决了ssh连接问题。你会通过-e "ssh -v"
。
答案 2 :(得分:0)
cygwin的rsync二进制分发是否识别ssh命令?当您放入shell时,您尝试执行的命令可能正常工作,因为像bash这样的东西知道如何解释ssh命令以建立连接,即使用ssh程序为rsync程序创建连接。根据您的调试信息,我认为rsync期望连接,但是收到一个字符串“ssh ...”,它无法管道。
要解决这个问题,你必须让bash为你工作。请查看有关线程的部分中的this page以了解孩子。您需要派生命令shell的实例并将命令写入shell子进程。所以像这样:
Process p = Runtime.getRuntime().exec("c:/cygwin/bin/bash.exe");
OutputStreamWriter osw = new OutputStreamWriter(p.getOutputStream());
BufferedWriter bw = new BufferedWriter( osw, 100);
try{
bw.write(command);
bw.close();
}catch(IOExeception e){
System.out.println("Problem writing command.");
}
您可能也想要读取进程输出,因为如果您不读它,它将停止执行。提供的链接很好地涵盖了这个主题。
答案 3 :(得分:0)
谢谢大家,特别是丹尼尔。你发给我的链接很棒。 最后我使用了ProcessBuilder而不是Runtime.exec。 如果对任何人有任何帮助,这是代码.....
ProcessBuilder pb = new ProcessBuilder(new String[]{"c:/cygwin/bin/rsync.exe"
,"-verbose",
"-r",
"-t",
"-v",
"--progress",
"-e",
"ssh",
"/cygdrive/c/Users/dokeeffe/workspace/jrsync/",
"www.servername.net:/home/dokeeffe/rsync/"});
Map<String, String> env = pb.environment();
env.put("PATH","/cygwin/bin;%PATH%");
pb.directory(new File("c:/cygwin/bin/"));
Process p = pb.start();
StreamGobbler outputGobbler = new StreamGobbler(p.getInputStream(),"OUTPUT");
StreamGobbler errorGobbler = new StreamGobbler(p.getErrorStream(),"ERROR");
outputGobbler.start();
errorGobbler.start();
int val = p.waitFor();
if(val!=0){
throw new Exception("Rsync return code="+val);
}
答案 4 :(得分:0)
我对类似问题的经验:
我的常数:
构建系统是ANT,在Hudson中运行
构建服务器是Windows Server
远程测试服务器是Linux
不允许仅通过ssh使用rsync守护进程rsync
我们做了什么
将DeltaCopy安装到Windows服务器
按照这些说明设置DeltaCopy,以便它可以使用SSH
我构建了以下ANT宏,并在hudson中运行它。 起初这件事挂在我身上,没有回应。
添加-vvv
而不是-v
会有所不同。这导致更多信息被添加到哈德森日志中。
<macrodef name="rsync">
<attribute name="username"/>
<attribute name="remoteServer"/>
<attribute name="remoteDir"/>
<attribute name="sourceDir"/> <!-- relative to basedir start and end with / (e.g. "/html/resources/" -->
<sequential>
<echo message="Starting rsync @{sourceDir} to @{remoteDir} on server @{remoteServer} as user @{username} at ${release.start}"/>
<pathconvert property="cygwinbasepath" dirsep="/" pathsep="" description="Replace ':' '\' with '/' and assign value to property">
<path path="${basedir}" description="Original version" />
<!--Pathconvert will try to add the root directory to the "path", replace with empty string -->
<filtermapper>
<replacestring from=":" to="" />
</filtermapper>
</pathconvert>
<echo message="${basedir} converted to ${cygwinbasepath}"/>
<property name="rsync.cygwinSourcePath" value="/cygdrive/${cygwinbasepath}@{sourceDir}" />
<!-- ${rsync.user}@${rsync.server}:${rsync.dir} -->
<property name="rsync.remoteDestinationPath" value="@{remoteServer}:@{remoteDir}" />
<echo message="trying to run:" />
<!-- " is escaped quote -->
<echo>cmd /C rsync -avz -e "ssh -v -l ${deployment.rsync.username} -i /cygdrive/C/cygwin/home/service-tomcat/.ssh/id_rsa" --recursive --chmod=a=rw,Da+x ${rsync.cygwinSourcePath} ${rsync.remoteDestinationPath}</echo>
<echo>
</echo>
<!-- 10 minute timeout -->
<exec executable="C:\cygwin\bin\mintty.exe"
timeout="300000"
>
<arg value="rsync"/>
<arg value="-avvvz"/>
<arg value="-e" />
<arg value="ssh -v -l ${deployment.rsync.username} -i /cygdrive/C/cygwin/home/vj-service-tomcat/.ssh/id_rsa" />
<arg value="--recursive"/>
<arg value="--chmod=a=rw,Da+x"/>
<arg value="${rsync.cygwinSourcePath}"/>
<arg value="${rsync.remoteDestinationPath}"/>
</exec>
<echo>
</echo>
</sequential>
实现这一目标的关键是执行C:\cygwin\bin\mintty.exe
而不是cmd
。
然后我在Windows服务器上手动运行rsync命令,使用远程主机更新其known_hosts文件。 这必须以hudson用户身份完成。我们在windows中使用runas命令以hudson用户身份启动cygwin控制台。
答案 5 :(得分:0)
我最近实现了类似的东西,并认为我会分享我的经验,因为它需要相当长的时间来调试问题。这个问题是google上这个问题的唯一例子之一。
我的应用程序是作为服务启动的。运行whoami命令时,结果是&#34; nt authority \ system&#34;。在/home/myusername/.ssh下设置了我的SSH密钥后,rsync命令失败,因为在/home/SYSTEM/.ssh下没有设置任何配置。
将我的/home/myusername/.ssh目录复制到/home/SYSTEM/.ssh并使用以下字符串数组可用于我的目的。用您的ssh端口替换PORT。
new String[]{"rsync", "-z", "-I", "-e", "ssh -p PORT", server + ":" + serverPath, clientPath}
有关在系统权限下启动cmd.exe以进行测试的详细信息,请参阅链接here。如果这是您的问题。