2017-10-09 162 views
0

在Windows系統上安裝了SSH,並且使用遠程主機(Linux)交換密鑰。我想在Windows機器上運行JAR到SCP文件到Linux機器。 與當JSch使用SCP時,如何逃避雙引號?

"C:/Program Files (X86)/ICW/bin/SCP.exe" -i .ssh/id_rsa <filename> [email protected]:/target/path/<filename> 

它工作得很好(使用雙引號)在命令行中執行此操作。

但是,當我使用JSch的JAR內運行SCP我得到一個sun.nio.file.InvalidPathException:非法字符< " >在指數...

的目的是,我有從FTP主機以編程方式收集一堆文件(我已經有這部分工作)。這些文件必須轉發到已經提到的遠程主機。 FTP主機和遠程主機不能直接通信。因此,Windows機器充當一種經紀人。 JAR從FTP服務器獲取文件(目前保存在地圖中),我想使用JSch SCP直接將它們放到遠程Linux主機上的特定文件夾中。

我該如何解決這個問題?如何解決這個雙引號問題

private void storeFiles() throws IOException { 
     final JSch jsch = new JSch(); 
     final FileSystem fs = FileSystems.getDefault(); 
     final Path p = fs.getPath(getProperty("scp.key.file.private")); 
     logger.info("Reading private key from " + getProperty("scp.key.file.private")); 

     final Session session; 
     try { 
      session = jsch.getSession(getProperty("scp.user.name"), getProperty("scp.host.ip"), 
        Integer.parseInt(getProperty("scp.port"))); 
      jsch.addIdentity(p.toFile().getPath()); 
      final Properties config = new java.util.Properties(); 
      config.put("StrictHostKeyChecking", "no"); 
      session.setConfig(config); 
      session.connect(); 
      logger.info("Connected to " + getProperty("scp.host.ip") + "..."); 

      vaFiles.forEach((k, v) ->{ 
       // get I/O streams for remote scp 
       try { 
        final MessageFormat mf = new MessageFormat(getProperty("scp.command")); 
        final Object[] commandArgs = new Object[]{getProperty("scp.key.file.private"), 
          k, getProperty("scp.user.name"), 
          getProperty("scp.host.ip"), 
          getProperty("scp.target.path"), k}; 
        final String command = mf.format(commandArgs); 
        logger.info(command); 
        final Channel channel; 
        try { 
         channel = session.openChannel("exec"); 
         channel.connect(); 
         ((ChannelExec)channel).setCommand(command); 
//      logger.info("Writing " + Arrays.toString(v) + " to SCP channel..."); 
         final OutputStream out = channel.getOutputStream(); 
         out.write(command.getBytes()); 
         out.flush(); 
         out.write(v); 
         out.close(); 
         channel.disconnect(); 
        } catch (JSchException e) { 
         e.printStackTrace(); 
        } 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 
      }); //end forEach 
      session.disconnect(); 
     } catch (JSchException e) { 
      e.printStackTrace(); 
     } 
    } 

。由此vaFiles是地圖<字符串,字節[] > 和scp.command來自屬性文件和是

scp.command = '\"C\:/Program\u0020Files\u0020(x86)/ICW/bin/scp.exe\"' -i {0} {1} {2}@{3}\:{4}/{5} 

(我試圖包裹在單個命令字符串雙引號,不含引號,不含\ u0020,...)

正在使用填充MessageFormat

{0} = '\ 「C:/程序\ u0020Files \ u0020(x86)的/ICW/bin/scp.exe \」'

{1} =文件名

{ 2} = SCP的用戶名

{3} = SCP HIST IP地址

{4} =遠程主機上的目標路徑

{5} =文件名(參見{1})

SFTP目前無法選擇,只有SCP安裝在Windows機器和遠程Linux主機上。 如果我在這方面有完全的誤解,我將不勝感激任何技術訣竅轉移,以瞭解如何以正確的方式做到這一點。 :-)

+1

請[編輯]你的問題,包括從你的程序中相關的源代碼。 – Kenster

+0

你確定要在服務器上執行'scp.exe'嗎?爲什麼? –

+0

因此,您在Windows機器上運行Java代碼,對吧?那麼爲什麼你通過JSch運行'scp.exe',如果你在本地運行它呢?如果您想從本地(Windows)機器傳輸文件,請使用本地JSch SCP(或更好的SFTP)實施。其實你的問題有一定道理。我真的不相信你會從JSch那裏得到'InvalidPathException'。這是一個本地例外。告訴我們你的代碼。 –

回答

1

你顯然是試圖發起從本地Windows機中的SCP文件傳輸到遠程Linux機。

但是你的代碼的確如此,它在ssh到遠程Linux機器上,並試圖在那裏運行Windows風格的命令C:\Program Files (x86)\ICW\bin\scp.exe。不管用什麼樣的引語,這都行不通。

  1. 不要使用SCP,它是一個古老的協議。使用SFTP。所有的Linux機器都支持SFTP。 JSch也具有對SFTP的本機支持。您不需要任何本地OpenSSH安裝。

  2. 即使您決定堅持SCP,將JSch SSH/SFTP庫與本地獨立SCP客戶端結合也沒有意義。

1

好,馬丁,謝謝你指導我在正確的方向。可能我會檢查並嘗試使用SFTP來實現它。 暫且你幫我實現至少使用SCP工作版本(即使它是一個古老的協議):

private void storeFilesSCP() throws IOException { 
    final JSch jsch = new JSch(); 
    final FileSystem fs = FileSystems.getDefault(); 
    final Path p = fs.getPath(getProperty("scp.key.file.private")); 
    logger.info("Reading private key from " + getProperty("scp.key.file.private")); 

    final Session session; 
    try { 
     session = jsch.getSession(getProperty("scp.user.name"), getProperty("scp.host.ip"), 
       Integer.parseInt(getProperty("scp.port"))); 
     jsch.addIdentity(p.toFile().getPath()); 
     final Properties config = new java.util.Properties(); 
     config.put("StrictHostKeyChecking", "no"); 
     session.setConfig(config); 
     final UserInfo userInfo = new UserInfo(); 
     session.setUserInfo(userInfo); 
     session.connect(); 
     logger.info("Connected to " + getProperty("scp.host.ip") + "..."); 

     vaFiles.forEach((k, v) ->{ 
      // get I/O streams for remote scp 
      try { 
       final Channel channel; 
       String command = "scp -t " + getProperty("scp.target.path") + "/" + k + " "; 
       System.out.println(command); 
       try { 
        channel = session.openChannel("exec"); 
        ((ChannelExec)channel).setCommand(command); 
        channel.connect(); 
        command="C0644 " + v.length + " " + k + "\n"; 
        System.out.println(command); 
        final OutputStream out = channel.getOutputStream(); 
        out.write(command.getBytes()); 
        out.flush(); 
        out.write(v); 
        out.flush(); 
        out.close(); 
        channel.disconnect(); 
       } catch (JSchException e) { 
        e.printStackTrace(); 
       } 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     }); //end forEach 
     session.disconnect(); 
    } catch (JSchException e) { 
     e.printStackTrace(); 
    } 
}