2009-03-26 2 views
1

У меня возникли проблемы с вызовом rsync из java на windows vista с установленным cygwin. Странно, что вставка одной и той же команды в командную оболочку отлично работает.Проблема с вызовом rsync + ssh из java на windows

Мой тестовый вызов 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 потоковых потока чтения для записи и входа в систему inputStream и errorStream процесса p.

Вот выход ....

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.

Если у кого есть какие-либо предложения, было бы здорово, как сейчас я застрял. Спасибо,

ответ

0

Существует ли бинарное распределение rsync cygwin в команде ssh? Команда, которую вы пытаетесь выполнить, работает отлично, когда вы помещаете ее в оболочку, потому что что-то вроде bash знает, как интерпретировать команду ssh для установления соединения, т. Е. Использовать программу ssh для создания соединения для программы rsync. Из вашей информации об отладке я думаю, что rsync ожидает соединение, но вместо этого получает строку «ssh ...», которую он не может выполнить.

Чтобы обойти это, вы должны позволить bash выполнить работу за вас. Посмотрите на this page в разделе о потоках, чтобы склонить ребенка. Вам нужно будет разбить экземпляр командной оболочки и записать команду в подпроцесс оболочки. Так что-то вроде этого:

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

Вы, вероятно, хотите, чтобы прочитать выходные данные процессы тоже, потому что он прекратит выполнение, если вы не читали его. Предоставленная ссылка хорошо освещает эту тему.

+0

Я рад, что это помогает. У меня была аналогичная проблема с попыткой выполнить «program

0

У вас есть приватное/общественное хранилище ssh где-то, о котором вы забыли?

+0

Да У меня есть настройка хранилища ключей, и команда работает нормально (без пароля), когда я вхожу в окно cmd или оболочку cygwin. – Derek

0

Я никогда не пробовал читать/писать, используя другой поток, только тот же поток, который выполнял эту команду. Может ли это быть причиной вашей проблемы?

Вы также можете попробовать передать -v в ssh, чтобы получить вывод отладки. Это помогло мне в прошлом решить проблемы с подключением ssh. Вы пройдете -e "ssh -v".

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); 
     } 
0

Мой опыт работы с подобным вопросом:

Мои константы:

  1. система сборки была ANT, работает в Хадсон

  2. сервер сборки Windows Server

  3. удаленный сервер тест Linux

  4. не разрешается использовать Rsync демон только Rsync через SSH

Что мы сделали

  1. Installed DeltaCopy на сервере окон

  2. Следуя этим инструкциям, чтобы установить DeltaCopy, он будет работать с SSH

  3. Я построил следующий ANT макрос, и запустил его в Гудзоне. Сначала это висело на мне, без ответа.

    Добавление -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. Затем я вручную выполнил команду rsync на сервере Windows, файл known_hosts обновлен удаленным хостом. Это должно было быть сделано как пользователь hudson. Мы использовали команду runas в Windows, чтобы запустить консоль cygwin в качестве пользователя hudson.

0

Недавно я реализовал нечто похожее и думал, что поделюсь своим опытом, так как потребовалось довольно много времени, чтобы отладить проблему. Этот вопрос является одним из единственных примеров этой проблемы в google.

Приложение было запущено как служба. При запуске команды whoami результатом является «nt authority \ system». Установив мои SSH-ключи в /home/myusername/.ssh, команда rsync терпела неудачу, так как в /home/SYSTEM/.ssh не была установлена ​​никакая настройка.

Копирование моего /home/myusername/.ssh каталога в /home/SYSTEM/.ssh и использование следующего массива String для моих целей. Замените PORT на ваш порт ssh.

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

Смотрите ссылку here для получения подробной информации о запуске cmd.exe под системными привилегиями для тестирования, если это ваша проблема.