2015-07-28 2 views
-1

Я пишу интеграционный тест JUnit, который общается с сервером Linux. Я использую библиотеки JSch для выполнения SSH и SFTP. Я заметил, что с PuTTY, изначально подключение к серверу с SSH занимает около 20 - 25 секунд, но как только я нахожусь, команды оболочки очень быстрые, когда они введены. Однако, когда я использую ссылку channelExec для выполнения системной команды, для каждой выполняемой команды требуется 20-25 секунд. Я бы хотел, чтобы команды были такими же быстрыми, как если бы я вводил их в PuTTY. Я заметил, что программа зависает, когда она считывает ввод с канала. Сессия JSch инициализируется до испытания выполняется здесь ...JSch ChannelExec Speedup

public void connectToServer() { 
    try { 
     JSch jsch = new JSch(); 
     session = jsch.getSession(sUserName, sHostName, 22); 
     session.setPassword(sPassword); 
     session.setConfig("StrictHostKeyChecking", "no"); 
     if (DEBUG_MODE) 
      println("UpdateProgram: Establishing SSH Connection..."); 
     session.connect(); 
     if (DEBUG_MODE) 
      println("UpdateProgram: SSH Connection established."); 
     if (DEBUG_MODE) println("UpdateProgram: Creating SFTP Channel."); 
     sftpChannel = (ChannelSftp) session.openChannel("sftp"); 
     sftpChannel.connect(); 
     if (DEBUG_MODE) println("UpdateProgram: SFTP Channel created."); 
    } 
    catch (Exception e) { 
     e.printStackTrace(); 
     System.exit(0); 
    } 
} 

сессия закрыта после того, как все тесты выполнены ...

public void exit() { 
    // Close SFTP Channel 
    if(sftpChannel != null) { 
     sftpChannel.disconnect(); 
     if (DEBUG_MODE) println("UpdateProgram: SFTP Channel closed."); 
    } 
    else { 
     if (DEBUG_MODE) 
      println("UpdateProgram: No SFTP Channel to close.");    
    } 

    // Close SSH resources 
    if (session != null) { 
     session.disconnect(); 
     if (DEBUG_MODE) println("UpdateProgram: SSH Disconnected."); 
    } 
    else { 
     if (DEBUG_MODE) 
      println("UpdateProgram: No SSH Connection to close."); 
    } 

    // Close DB2 database resources 
    if (conn != null) { 
     try { 
      conn.close(); 
      if (DEBUG_MODE) println(
        "UpdateProgram: Connection to DB2 database closed."); 
     } 
     catch (Exception e) { 
      e.printStackTrace(); 
      System.exit(0); 
     } 
    } 
    else { 
     if (DEBUG_MODE) 
      println("UpdateProgram: No DB2 database connection to close."); 
    } 
} 

Вот мой тест, который вызывает runCProgram (метод), который обрабатывает экземпляр ChannelExec ...

public void effDateBeforeYesterday() { 
    String effDate = null, 
      testRec = null; 

    // Set effective date 
    if(dateSize == 6) 
     effDate = "000000"; 
    else 
     effDate = "00000000"; 

    // Upload Base test case and run C program 
    program.setTransCount(5); 
    program.put(); 
    program.runCProgram(); 

    // Upload test record 
    testRec = effDisDateInsert(effDate, currDate, true) + "\n"; 
    IO.fileWrite(testRec, file); 
    program.setTransCount(1); 
    program.put(); 
    program.runCProgram(); 

    // Query database for results 

    // Clear table for next test 

    assertTrue(true); 
} 

runCProgram() метод:

public void runCProgram() { 
    String command = "cd " + updateProgramPath + " && " + "./" + updateProgram 
      + " -tc -b. -ppackage -r20150601000000 -n" + transCount + " -d" 
      + dbName + " -u" + dbUserName + " -w" + dbPassword + " -s" 
      + scheduleName; 
    ChannelExec channel = null; 
    InputStream in = null; 

    try { 
     // Setup channel for system command execution 
     channel = (ChannelExec) session.openChannel("exec"); 
     if (DEBUG_MODE) println("UpdateProgram: Exec channel created."); 
     channel.setCommand(command); 
     if (DEBUG_MODE) 
      println("UpdateProgram: Linux Command set to: " + command); 
     channel.setInputStream(null); 
     channel.setErrStream(System.err); 
     in = channel.getInputStream(); 

     channel.connect(); 

     // Used for error detection in C program 
     int temp = 0; 

     if (DEBUG_MODE) println("UpdateProgram: Linux output: "); 
     byte[] tmp = new byte[1024]; 
     while (true) { 
      while (in.available() > 0) { 
       int i = in.read(tmp, 0, 1024); 
       if (i < 0) break; 
       System.out.print(new String(tmp, 0, i)); 
      } 
      if (channel.isClosed()) { 
       if (in.available() > 0) continue; 
       temp = channel.getExitStatus(); 
       if (temp != 0) throw new Exception(
         "C Program Error, exit status " + temp); 
       System.out.println("UpdateProgram: exit-status: " + temp); 
       break; 
      } 
      try { 
       Thread.sleep(1000); 
      } 
      catch (Exception ee) {} 
     } 

     channel.disconnect(); 
     if (DEBUG_MODE) println("UpdateProgram: Exec channel closed."); 
    } 

Кажется, что для каждой команды создается новое соединение. Есть ли способ ускорить ссылку ChannelExec, чтобы он мог быстро выполнять системные команды? Любая помощь будет принята с благодарностью!

+0

Ваш код выполняет только одну команду. Как мы можем вам помочь, если мы не знаем, что вы делаете для выполнения других команд? –

+0

Извините за неправильный пример кода. Вот мой фактический код. –

+0

Мы до сих пор не можем видеть, как и когда вы создаете 'session'. –

ответ

0

Хорошо, поэтому я нашел обходной путь к моей проблеме. Я использовал канал оболочки вместо exec, чтобы я мог выполнять команды в любое время во время моей программы. Вот мой код для запуска оболочки ...

// Global variables 
PrintStream shellInput; 
PipedInputStream pin2; 

private void connectShell() { 
    PipedInputStream pin = null; 
    PipedOutputStream pout = null; 
    PipedOutputStream pout2 = null; 
    String tmpStr = null; 
    byte[] tmp = null; 

    try { 
     // Setup for channel I/O 
     pin = new PipedInputStream(); 
     pout = new PipedOutputStream(pin); 
     pout2 = new PipedOutputStream(); 
     pin2 = new PipedInputStream(pout2); 
     shellInput = new PrintStream(pout); 

     // Create channel 
     shellChannel = session.openChannel("shell"); 
     shellChannel.setInputStream(pin); 
     shellChannel.setOutputStream(pout2); 
     if (DEBUG_MODE) 
      println("UpdateProgram: Connecting to remote shell..."); 
     shellChannel.connect(); 

     // Block until shell is connected 
     tmpStr = ""; 
     tmp = new byte[1024]; 
     while (!tmpStr.contains("Username String")) { 
      while (pin2.available() > 0) { 
       int i = pin2.read(tmp, 0, 1024); 
       tmpStr = new String(tmp, 0, i); 
       if (i < 0) break; 
       print(tmpStr); 
      } 
      Thread.sleep(1000); 
     } 

     if (DEBUG_MODE) 
      println("UpdateProgram: Connected to remote shell."); 
    } 
    catch (Exception e) { 
     e.printStackTrace(); 
     System.exit(0); 
    } 
} 

Я использую shellInput для отправки команд в оболочку, и PIN2 читать выход из оболочки. Спасибо, Мартин Прикрилл за вашу помощь!

Смежные вопросы