1

我在安装了 cygwin 的 windows vista 上从 java 调用 rsync 时遇到问题。将完全相同的命令粘贴到命令外壳中可以正常工作,这很奇怪。

我的测试 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) < 0 或 fd_pair(from_child_pipe) < 0。

如果有人有任何建议,那就太好了,因为我现在被困住了。谢谢,

4

6 回答 6

0

您是否在某处忘记了 ssh 私有/公共密钥库?

于 2009-03-26T17:29:19.783 回答
0

我从来没有尝试过使用不同的线程读/写,只有执行命令的同一个线程。这会导致您的问题吗?

您也可以尝试将 -v 传递给 ssh 以获取调试输出。这在过去帮助我解决了 ssh 连接问题。你会通过-e "ssh -v"的。

于 2009-03-26T21:16:47.053 回答
0

cygwin 的 rsync 二进制分发版能识别 ssh 命令吗?当您放入 shell 时,您尝试执行的命令可能工作正常,因为 bash 之类的东西知道如何解释 ssh 命令以建立连接,即使用 ssh 程序为 rsync 程序创建连接。从您的调试信息中,我认为 rsync 正在等待连接,而是收到了一个无法通过管道传输的字符串“ssh ...”。

要解决这个问题,您必须让 bash 为您完成工作。在线程部分中查看此页面以照顾孩子。您需要派生一个命令外壳的实例并将您的命令写入外壳子进程。所以是这样的:

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.");
}

您可能还想阅读进程输出,因为如果您不阅读它,它将停止执行。提供的链接很好地涵盖了该主题。

于 2009-03-26T21:17:20.357 回答
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);
        }
于 2009-03-26T23:22:50.493 回答
0

我对类似问题的经验:

我的常数:

  1. 构建系统是 ANT,在 Hudson 运行

  2. 构建服务器是 Windows Server

  3. 远程测试服务器是 Linux

  4. 不允许使用 rsync 守护进程,仅 rsync over ssh

我们做了什么

  1. 将 DeltaCopy 安装到 windows 服务器

  2. 按照这些说明设置 DeltaCopy,以便它可以与 SSH 一起使用

  3. 我构建了以下 ANT 宏,并在 hudson 中运行它。起初,这挂在我身上,没有任何反应。

    添加-vvv而不是-v做出不同的。这导致更多信息被添加到 hudson 日志中。

    <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:" />
        <!-- &quot; is escaped quote -->
        <echo>cmd /C rsync -avz -e &quot;ssh -v -l ${deployment.rsync.username} -i /cygdrive/C/cygwin/home/service-tomcat/.ssh/id_rsa&quot; --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.

  4. 然后,我在 Windows 服务器上手动运行 rsync 命令,其 known_hosts 文件已使用远程主机进行更新。这必须以 hudson 用户的身份完成。我们在 windows 中使用 runas 命令以 hudson 用户身份启动 cygwin 控制台。

于 2012-08-01T05:24:22.603 回答
0

我最近实现了类似的东西,并认为我会分享我的经验,因为调试问题需要相当长的时间。这个问题是谷歌上这个问题的唯一实例之一。

我的应用程序作为服务启动。运行 whoami 命令时,结果是“nt authority\system”。在 /home/myusername/.ssh 下设置了我的 SSH 密钥后,rsync 命令失败,因为 /home/SYSTEM/.ssh 下没有设置任何配置。

将我的 /home/myusername/.ssh 目录复制到 /home/SYSTEM/.ssh 并使用以下字符串数组可以满足我的目的。将 PORT 替换为您的 ssh 端口。

new String[]{"rsync", "-z", "-I", "-e", "ssh -p PORT", server + ":" + serverPath, clientPath}

如果这是您的问题,请参阅此处的链接以获取有关在系统权限下启动 cmd.exe 以进行测试的详细信息。

于 2016-10-25T16:28:17.030 回答