Jsch - One Session Multiple Channels

24,440

Solution 1

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".

Solution 2

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)
         {
         }
      }
   }
}

Solution 3

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

Solution 4

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

Solution 5

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) {
}
Share:
24,440
Nick Russler
Author by

Nick Russler

Updated on February 01, 2020

Comments

  • Nick Russler
    Nick Russler about 4 years

    I managed to execute a single command through ssh with Jsch but when i try to execute a second command it fails

    For debugging i brought this problem down to this lines:

    import java.io.IOException;
    import java.io.InputStream;
    
    import com.jcraft.jsch.Channel;
    import com.jcraft.jsch.ChannelExec;
    import com.jcraft.jsch.JSch;
    import com.jcraft.jsch.JSchException;
    import com.jcraft.jsch.Session;
    
    public class Exec {
    
        public static void test(Session session) throws Exception {
            Channel channel = session.openChannel("exec");
            ((ChannelExec) channel).setCommand("pwd");
    
            channel.setInputStream(null);
    
            ((ChannelExec) channel).setErrStream(System.err);
    
            InputStream in = channel.getInputStream();
    
            channel.connect();
    
            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()) {
                    System.out.println("exit-status: " + channel.getExitStatus());
                    break;
                }
                try {
                    Thread.sleep(1000);
                } catch (Exception ee) {
                }
            }
            channel.disconnect();
        }
    
        public static void main(String[] arg) {
            try {
                JSch jsch = new JSch();         
                Session session = jsch.getSession("nck", "127.0.0.1", 22);          
                session.setPassword("asd");         
                session.setConfig("StrictHostKeyChecking", "no");           
                session.connect();
    
                test(session); // This one succeeds with exit-status: 0         
                test(session); // This one fails with exit-status: 255
    
                session.disconnect();
            } catch (Exception e) {
                //
            }
        }
    }
    

    This is mostly the official Exec example but this gives me this output:

    /home/nck
    exit-status: 0
    exit-status: 255
    

    The first command is executed succesfully the second doesnt.

    Any Ideas ?

  • svarog
    svarog about 7 years
    I tried all solutions and this is the best solution