title: JSch ChannelExec Speedup
body: <p>I am writing a JUnit integration test that communicates with a Linux server. I am using the JSch libraries to perform SSH, and SFTP. I noticed with PuTTY, initially connecting to the server with SSH takes about 20 - 25 seconds, but once I'm in, shell commands are really quick when entered. However, when I use a channelExec reference to perform a system command, it takes that same 20 - 25 seconds for every command that is executed. I would like the commands to be as quick as if I were inputting them in PuTTY. I noticed the program gets hung up when it is reading input from the channel. The JSch session is initialized before the tests are executed here...</p>
  
  <pre><code>    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);
      }
  }
  </code></pre>
  
  <p>The session is closed after all the tests are complete...</p>
  
  <pre><code>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.");
      }
  }
  </code></pre>
  
  <p>Here is my test that calls the runCProgram() method that handles the ChannelExec instance...</p>
  
  <pre><code>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);
  }
  </code></pre>
  
  <p>runCProgram() method:</p>
  
  <pre><code>    public void runCProgram() {
      String command = "cd " + updateProgramPath + " &amp;&amp; " + "./" + 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() &gt; 0) {
                  int i = in.read(tmp, 0, 1024);
                  if (i &lt; 0) break;
                  System.out.print(new String(tmp, 0, i));
              }
              if (channel.isClosed()) {
                  if (in.available() &gt; 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.");
      }
  </code></pre>
  
  <p>It seems as though a new connection is being made for each command. Is there a way to speed up a ChannelExec reference so that it can execute system commands quickly? Any help would be greatly appreciated!</p>