0

I am using JSch to connect to SSH and execute commands. One of the commands gives out a big output. In terminal if you execute the command you have to press enter to see the entire output. Using JSch I am not able to retrieve the entire output.

When I login using an interactive terminal, the command output stops after filling a screen and waits for Enter.

The code is taken from How to get jsch shell command output in String:

public class SshConnectionManager {

    private static Session session;
    private static ChannelShell channel;
    private static String username = "";
    private static String password = "";
    private static String hostname = "";


    private static Session getSession(){
        if(session == null || !session.isConnected()){
            session = connect(hostname,username,password);
        }
        return session;
    }

    private static Channel getChannel(){
        if(channel == null || !channel.isConnected()){
            try{
                channel = (ChannelShell)getSession().openChannel("shell");
                channel.connect();

            }catch(Exception e){
                System.out.println("Error while opening channel: "+ e);
            }
        }
        return channel;
    }

    private static Session connect(String hostname, String username, String password){

        JSch jSch = new JSch();

        try {

            session = jSch.getSession(username, hostname, 22);
            Properties config = new Properties(); 
            config.put("StrictHostKeyChecking", "no");
            session.setConfig(config);
            session.setPassword(password);

            System.out.println("Connecting SSH to " + hostname + " - Please wait for few seconds... ");
            session.connect();
            System.out.println("Connected!");
        }catch(Exception e){
            System.out.println("An error occurred while connecting to "+hostname+": "+e);
        }

        return session;

    }

    private static void executeCommands(List<String> commands){

        try{
            Channel channel=getChannel();

            System.out.println("Sending commands...");
            sendCommands(channel, commands);

            readChannelOutput(channel);
            System.out.println("Finished sending commands!");

        }catch(Exception e){
            System.out.println("An error ocurred during executeCommands: "+e);
        }
    }

    private static void sendCommands(Channel channel, List<String> commands){

        try{
            PrintStream out = new PrintStream(channel.getOutputStream());

            out.println("#!/bin/bash");
            for(String command : commands){
                out.println(command);
            }
            out.println("exit");

            out.flush();
        }catch(Exception e){
            System.out.println("Error while sending commands: "+ e);
        }

    }

    private static void readChannelOutput(Channel channel){

        byte[] buffer = new byte[1024];

        try{
            InputStream in = channel.getInputStream();
            String line = "";
            while (true){
                while (in.available() > 0) {
                    int i = in.read(buffer, 0, 1024);
                    if (i < 0) {
                        break;
                    }
                    line = new String(buffer, 0, i);
                    System.out.println(line);
                }

                if(line.contains("logout")){
                    break;
                }

                if (channel.isClosed()){
                    break;
                }
                try {
                    Thread.sleep(1000);
                } catch (Exception ee){}
            }
        }catch(Exception e){
            System.out.println("Error while reading channel output: "+ e);
        }

    }

    public static void close(){
        channel.disconnect();
        session.disconnect();
        System.out.println("Disconnected channel and session");
    }


    public static void main(String[] args){
        List<String> commands = new ArrayList<String>();
        commands.add("ls -l");

        executeCommands(commands);
        close();
    }
}
Community
  • 1
  • 1
Charity
  • 213
  • 1
  • 5
  • 21
  • There are lots different pieces of code in the question you link to. Show us your code! – Martin Prikryl Feb 19 '16 at 11:30
  • Check the SshConnectionManager code inside the link. I am using the same code for ssh connection and execution. It is the answer with three up votes – Charity Feb 19 '16 at 11:55
  • If you connect with PuTTY with *"Connection > SSH > TTY > Don't allocate a pseudo-terminal"* option turned on, do you still need to press the Enter to see a full output? – Martin Prikryl Feb 19 '16 at 12:10
  • i was not able to connect if the option is ticked. Connection is timing out – Charity Feb 19 '16 at 13:57
  • Does does not make sense. Can you connect if you untick it? – Martin Prikryl Feb 19 '16 at 14:12
  • Yes i was able to connect now. when i tick this option i was able to see the output on console without pressing enter. So could you tell me how to do this same thing in above code – Charity Feb 19 '16 at 14:18

1 Answers1

3

You generally should not use "shell" channel to automate a command execution.

The "shell" channel is intended to implement an interactive shell session.

Hence it requests PTY (pseudo-terminal), which has human-friendly, but machine-unfriendly, side-effects that break your code.

Use "exec" channel instead.

See Execute a list of commands from an ArrayList using JSch exec in Java


If you need or want to use the "shell" channel for some reason (but do not, it will bite you anyway), make sure you call .setPty(false) before .connect:

channel = (ChannelShell)getSession().openChannel("shell");
channel.setPty(false);
channel.connect();

Side notes:

Community
  • 1
  • 1
Martin Prikryl
  • 167,268
  • 50
  • 405
  • 846