Question

I can't figure it out how I can send commands via JSch shell channel.

I do this, but it doesn't work:

JSch shell = new JSch();
String command = "cd home/s/src";  
Session session = shell.getSession(username, host, port);  
MyUserInfo ui = new MyUserInfo();  
ui.setPassword(password);  
session.setUserInfo(ui);  
session.connect();  

channel = session.openChannel("shell");  
fromServer = new BufferedReader(new InputStreamReader(channel.getInputStream()));  
toServer = channel.getOutputStream();
channel.connect();  
toServer.write((command + "\r\n").getBytes());
toServer.flush();

and then I read input like this:

StringBuilder builder = new StringBuilder();  

int count = 0;  
String line = "";  

while(line != null) {  
    line = fromServer.readLine();
    builder.append(line).append("\n");

    if (line.endsWith(".") || line.endsWith(">")){
        break;
    }
}  
String result = builder.toString();  
ConsoleOut.println(result);
Was it helpful?

Solution

If it hangs at readLine() that means either your "while" is never ending (might be unlikely considering your code), or, readLine() is waiting for its source, namely the IOstream blocks the thread cause available()!=true.

I can't quite troubleshoot your code without seeing your debug info. But as an advice, have you tried PipedIntputStream? The idea is to pipe your console input to "your" output so that you can "write" it. To implement this, you need to initialize the in/out-put.

InputStream in = new PipedInputStream();
PipedOutputStream pin = new PipedOutputStream((PipedInputStream) in);
/**...*/
channel.setInputStream(in);
channel.connect();
/** ...*/
pin.write(myScript.getBytes());

The same goes to your question, how to read console output.

PipedInputStream pout = new PipedInputStream((PipedOutputStream) out);
/**
* ...
*/
BufferedReader consoleOutput = new BufferedReader(new InputStreamReader(pout));
consoleOutput.readLine();

And again, if you are not sure how many lines to read and thus want to use "while", make sure you do something inside while to prevent 1) busy-waiting 2) ending-condition. Example:

while(!end)
{
   consoleOutput.mark(32);
   if (consoleOutput.read()==0x03) end = true;//End of Text
   else
   { 
     consoleOutput.reset();
     consoleOutput.readLine();
     end = false;
   }
}

OTHER TIPS

Try this:

JSch jsch = new JSch();

try
{
  Session session = jsch.getSession("root", "192.168.0.1", 22);
  java.util.Properties config = new java.util.Properties();
  config.put("StrictHostKeyChecking", "no");
  session.setConfig(config);

  session.connect();

  String command = "lsof -i :80";
  Channel channel = session.openChannel("exec");
  ((ChannelExec) channel).setCommand(command);
  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();
  session.disconnect();
}
catch (Exception e)
{
  System.out.println(e.getMessage());
}

Following was a quickly written code for my assignment. Not a well done program. But serves its purpose.

  1. Connects via SSH (using Jsch) to a server (using a Private Key File - mykey.pem)
  2. Creates a shell script (to mount a volume and mkfs)
  3. Runs on the remote machine
  4. All the while you can see the output on your stdout

The code follows:

public class connectSSH {

public void connect(String dnsName, String privKey) throws IOException {
    JSch jSch = new JSch();

    try {

                    //Authenticate through Private Key File
        jSch.addIdentity(privKey);
                    //Give the user and dnsName
        Session session = jSch.getSession("root", dnsName, 22);
                    //Required if not a trusted host
        java.util.Properties config = new java.util.Properties(); 
        config.put("StrictHostKeyChecking", "no");
        session.setConfig(config);
        System.out.println("Connecting SSH to " + dnsName + " - Please wait for few minutes... ");
        session.connect();
            //Open a shell 
        Channel channel=session.openChannel("shell");
        channel.setOutputStream(System.out);
            //Create a Shell Script
        File shellScript = createShellScript();
            //Convert the shell script to byte stream
        FileInputStream fin = new FileInputStream(shellScript);
        byte fileContent[] = new byte[(int)shellScript.length()];
        fin.read(fileContent);
        InputStream in = new ByteArrayInputStream(fileContent);
            //Set the shell script to the channel as input stream
        channel.setInputStream(in);
            //Connect and have fun!
        channel.connect();          

    } catch (JSchException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}

public File createShellScript() {
     String filename = "shellscript.sh";
     File fstream = new File(filename);

     try{
          // Create file 
         PrintStream out = new PrintStream(new FileOutputStream(fstream));
         out.println("#!/bin/bash");
         out.println("echo \"hi\" > /tmp/test.info");
         out.println("echo \"n\" > /tmp/fdisk.in");
         out.println("echo \"p\" >> /tmp/fdisk.in");
         out.println("echo \"1\" >> /tmp/fdisk.in");
         out.println("echo >> /tmp/fdisk.in");
         out.println("echo >> /tmp/fdisk.in");
         out.println("echo \"w\" >> /tmp/fdisk.in");

         out.println("/sbin/fdisk /dev/sdf < /tmp/fdisk.in");
         out.println("mkfs.ext3 /dev/sdf1");
         out.println("mkdir /usr/myebs");
         out.println("mount /dev/sdf1 /usr/myebs");
         out.println("partprobe /dev/sdf1");

         out.println("echo \"Success\"");

         //Close the output stream
         out.close();
     }catch (Exception e){//Catch exception if any
         System.err.println("Error: " + e.getMessage());
     }
     return fstream;

}

public static void main(String[] args) {
    connectSSH ssh = new connectSSH();
    String privKey = "/Users/neo/Desktop/mykey.pem";
    try {
        ssh.connect("yourexampleserver.com", privKey);
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}

}
private void executeRemoteCommandAsSudo(String sudoAs, String password,
            String command, int delayInSeconds) 
{
    logger.info("executeRemoteCommandAsSudo started....");
    logger.info("sudoAs=" + sudoAs);
    logger.info("command=" + command);
    logger.info("delayInSeconds=" + delayInSeconds);
    Session session = null;
    Channel channel = null;
    try {
        session = getSession();
        channel = session.openChannel("exec");
        String sudoCommand = "sudo su - " + sudoAs;
        ((ChannelExec) channel).setCommand(sudoCommand);
        ((ChannelExec) channel).setPty(true);
        channel.connect();
        InputStream inputStream = channel.getInputStream();
        OutputStream out = channel.getOutputStream();
        ((ChannelExec) channel).setErrStream(System.err);
        out.write((password + "\n").getBytes());
        out.flush();
        Thread.sleep(1000);
        out.write((command + "\n").getBytes());
        out.flush();
        Thread.sleep(1000 * delayInSeconds);
        out.write(("logout" + "\n").getBytes());
        out.flush();
        Thread.sleep(1000);
        logInfo(channel, inputStream);
        out.write(("exit" + "\n").getBytes());
        out.flush();
        out.close();
        Thread.sleep(1000);
    } catch (Exception ex) {
        logger.error(ex.getMessage());
    } finally {
        session.disconnect();
        channel.disconnect();
    }
    logger.info("executeRemoteCommandAsSudo completed....");
}
private void logInfo(Channel channel, InputStream in) 
{
    try {
        byte[] tmp = new byte[1024];
        while (true) {
            while (in.available() > 0) {
                int i = in.read(tmp, 0, 1024);
                if (i < 0)
                    break;
                logger.info(new String(tmp, 0, i));
            }
            if (channel.isClosed()) {
                logger.info("exit-status: " + channel.getExitStatus());
                break;
            }
        }
    } catch (Exception ex) {
        logger.error(ex);
    }
}

private Session getSession() throws JSchException 
{
    JSch jsch = new JSch();
    logger.info("ftpUser=" + ftpUser);
    logger.info("ftpHost=" + ftpHost);
    Session session = jsch.getSession(ftpUser, ftpHost, 22);
    session.setPassword(ftpPassword);
    java.util.Properties config = new java.util.Properties();
    config.put("StrictHostKeyChecking", "no");
    session.setConfig(config);
    session.connect();
    return session;
}

With piped input and output streams seems interesting:

JSch jsch = new JSch();
jsch.addIdentity("/home/audrius/.ssh/blablabla", "blablablabla");

String user = "audrius";
String host = "ultrastudio.org";

Session session = jsch.getSession(user, host, 439);
session.setConfig("StrictHostKeyChecking", "no");           
session.connect();

Channel channel = session.openChannel("shell");

PipedInputStream pip = new PipedInputStream(40);
channel.setInputStream(pip);

PipedOutputStream pop = new PipedOutputStream(pip);
PrintStream print = new PrintStream(pop);           
channel.setOutputStream(System.out);

print.println("ls");

I realize that this is an old thread, but I have struggled with a similar problem today. This is my solution.

public class ChannelConsole {

// ================================================
// static fields
// ================================================

// ================================================
// instance fields
// ================================================

private Session session;

// ================================================
// constructors
// ================================================

public ChannelConsole(Session session) {
    this.session = session;
}

// ================================================
// getters and setters
// ================================================

// ================================================
// public methods
// ================================================

public String execute(String command) throws JSchException {
    command = command.trim() + "\n";

    ChannelExec channel = (ChannelExec) this.session.openChannel("exec");
    channel.setCommand(command);

    ByteArrayOutputStream responseStream = new ByteArrayOutputStream();
    channel.setOutputStream(responseStream);

    channel.connect();

    try {
        awaitChannelClosure(channel);
    } catch (InterruptedException e) {
        // no one cares
    }

    String result = responseStream.toString();
    closeQuietly(responseStream);
    return result;

}

// ================================================
// private methods
// ================================================

private void awaitChannelClosure(ChannelExec channel) throws InterruptedException {
    while (channel.isConnected()) {
        Thread.sleep(100);
    }
}

private static void closeQuietly(Closeable closeable) {
    if (closeable == null) {
        return;
    }

    try {
        closeable.close();
    } catch (IOException ignored) {
        ignored.printStackTrace();
    }
}

}

Using this class you can just do something like : shell = new ChannelConsole(this.session); String result = shell.execute("quota -v; echo; echo \"Disk storage information:\"; df -hk")

try this

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

Usage:

String remoteCommandOutput = exec("ssh://user:pass@host/work/dir/path", "ls -t | head -n1");
String remoteShellOutput = shell("ssh://user:pass@host/work/dir/path", "ls")
shell("ssh://user:pass@host/work/dir/path", "ls", System.out)
shell("ssh://user:pass@host", System.in, System.out);

Implementation

try this code :

         JSch jsch=new JSch();

         System.out.println("Getting session");
         Session session=jsch.getSession("root","10.0.0.0",22);

          System.out.println("session is ::::"+session.getHost());
          // username and password will be given via UserInfo interface.
          UserInfo ui = new MyUserInfo("Lab@123", null);
          //UserInfo ui = new MyUserInfo(password, null);
          session.setUserInfo(ui);
          session.setPassword("Lab@123");
          Properties config = new java.util.Properties();
          config.put("StrictHostKeyChecking", "no");
          session.setConfig(config);
          session.connect(40000);


              Channel channel=session.openChannel("exec"); 
              ((ChannelExec)channel).setCommand("ls");

              channel.connect();
              channel.run();

              // get I/O streams for remote scp
              OutputStream out=channel.getOutputStream();
              InputStream in=channel.getInputStream(); 


          String output="";
          while (channel.isClosed()!=true) {

              try {
                output+=streamToString(in);

            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }

            System.out.println("Output is :::"+output);
            channel.disconnect();
            session.disconnect();
    }

    public static String streamToString(InputStream input)throws Exception 
    { String output = ""; while(input.available()>0) { output += ((char)(input.read())); } return output; }



    public static OutputStream stringToStream(String charset) throws IOException{

        byte[] bytes = charset.getBytes();
        /*ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
        InputStreamReader isr = new InputStreamReader(bais);*/
        InputStream is = null;
        OutputStream os = null;
        try {
            is = new ByteArrayInputStream(charset.getBytes("UTF-8"));
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        //byte[] buf = new byte[1024];
        int numRead;

          while ( (numRead = is.read(bytes) ) >= 0) {
              os.write(bytes, 0, numRead);
          }        
        return os;      
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top