Jsch - One Session Multiple Channels

◇◆丶佛笑我妖孽 提交于 2019-11-30 10:28:23
Simon Schubert

Hey I have exactly the same problem with jsch and Ubuntu. (How) did you solve it? Making a new session for every execute eats too much time? At the moment I catch the jsch exception and search for "session isn't down" then I reconnect the session and execute command again. That works but is not a good solution.

Edit: I was on the wrong way I solved my problem for now by using

channel = session.openChannel("shell");

instead of "exec".

Here is a complete working Java class based on @krishna's answer:

/**
 * Run several ssh commands in a single JSch session
 */
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import java.io.*;

class SshMultiCommands
{
   public static void main(String[] args) throws Exception
   {
      JSch jsch = new JSch();
      String user = "user";            //CHANGE ME
      String host = "192.168.222.157"; //CHANGE ME
      String passwd = "password";      //CHANGE ME
      int port = 22;    
      Session session = jsch.getSession(user, host, port);
      session.setPassword(passwd);

      session.setConfig("StrictHostKeyChecking", "no");

      session.connect();

      Channel channel = session.openChannel("shell");
      OutputStream ops = channel.getOutputStream();
      PrintStream ps = new PrintStream(ops, true);

      channel.connect();
      InputStream input = channel.getInputStream();

      //commands
      ps.println("ls -lag");
      ps.println("cd /etc");
      ps.println("ls");
      ps.println("exit");
      ps.close();

      printResult(input, channel);

      channel.disconnect();
      session.disconnect();
   }

   /**
    * @param input
    * @param channel
    */
   private static void printResult(InputStream input,
                                   Channel channel) throws Exception
   {
      int SIZE = 1024;
      byte[] tmp = new byte[SIZE];
      while (true)
      {
         while (input.available() > 0)
         {
            int i = input.read(tmp, 0, SIZE);
            if(i < 0)
               break;
             System.out.print(new String(tmp, 0, i));
         }
         if(channel.isClosed())
         {
            System.out.println("exit-status: " + channel.getExitStatus());
            break;
         }
         try
         {
            Thread.sleep(300);
         }
         catch (Exception ee)
         {
         }
      }
   }
}
krishna

you can use shell to execute multiple commands. following is the code to execute commands via shell.

Channel channel=session.openChannel("shell");
OutputStream ops = channel.getOutputStream();
PrintStream ps = new PrintStream(ops, true);

channel.connect();
ps.println("mkdir folder"); 
ps.println("dir");
//give commands to be executed inside println.and can have any no of commands sent.
ps.close();

InputStream in=channel.getInputStream();
byte[] bt=new byte[1024];

while(true) {
    while(in.available()>0) {
        int i=in.read(bt, 0, 1024);
        if(i<0)
            break;
        String str=new String(bt, 0, i);

        //displays the output of the command executed.
        System.out.print(str);
    }
    if(channel.isClosed()) 
        break;

    Thread.sleep(1000);
    channel.disconnect();
    session.disconnect();   
}

I used exactly same code and had problem some of the times reading output of the script i executed through ssh. Sometimes the program was missing the all content, and sometime only a part of the content. I resolved my problem by changing the if(channel.isclosed) in the nested loop. Here is the new code

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) {
                int i = in.read(tmp, 0, 1024);
                System.out.print(new String(tmp, 0, i));
             } 
            System.out.println("exit-status: " + channel.getExitStatus());
            break;
        }
        try {
            Thread.sleep(1000);
        } catch (Exception ee) {
}
Musaddique

If you want to use exec. you can run multiple commands by putting a semi colon (;) within commands

like:

pwd;ls- -l; 
cd foldername

((ChannelExec) channel).setCommand("pwd;ls -l; cd foldername");
Nick Russler

This wasn't a bug in jsch, it was a bug of my ssh server (cygwin - I bet I configured something wrong...)

Edit: hmm I had the same problem with jsch with Ubuntu ... weird

Guess as workarround I'll have to open a new session for each query.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!