hierynomus / sshj

ssh, scp and sftp for java
Apache License 2.0
2.5k stars 601 forks source link

No data from the InputStream #251

Open ramakrishnagorrela opened 8 years ago

ramakrishnagorrela commented 8 years ago

Hi, I am completely new to this API, I'm using this API to get the target device(Cisco IOS) configuration with few commands like show running-config.. Here I'm facing one challenge while using this API on a few devices,

Scenario: I'm connecting to a device through sshj to retrieve the device configuration by executing commands on the target host, able to connect to the device and executing commands properly but facing one challenge here, I'm unable to retrieve whole configuration from the target device, it is only giving half of the data from the target host then there is no data in Input stream, please help me out from this

Code snippet : public class Exec {

public static void main(String... args) throws Exception { final SSHClient ssh = new SSHClient(); try { ssh.addHostKeyVerifier(new PromiscuousVerifier()); ssh.loadKnownHosts(); } catch (Exception e) {

} ssh.connect("XX.XX.XX.XX", 22); try { ssh.authPassword("username", "password"); Session session = ssh.startSession(); InputStream inputstream = session.getInputStream(); OutputStream outputstream = session.getOutputStream(); session.allocateDefaultPTY(); // Tried with other PTY method like vt102,exterm.. session.startShell(); new Thread() { public synchronized void run() { try { int len = 0; while (len != -1) { byte[] buf = new byte[1024 * 10]; len = inputstream.read(buf, 0, buf.length); System.out.println( new String(buf, 0, 1024 * 10)); } }catch(Exception e){ e.getMessage(); } } }.start(); try { outputstream.write(("show running-config" + "\n").getBytes()); outputstream.flush(); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } } finally { session.close(); } } finally { ssh.disconnect(); } } }

Note : we have tried with VT100,VT102 and xterm PTY types and also we have suspected issue with sleep time initially then increased sleep time but no luck. please help me out Thanks, RamaKrishna.

markspeters commented 8 years ago

Hi RamaKrishna,

From your code, it looks like you're reading the data in 10240 byte chunks. Most InputStream implementations will block until either the full chunk has been filled, or end of stream has been reached:

The default implementation of this method blocks until the requested amount of input data len has been read, end of file is detected, or an exception is thrown.

Because SSH is an interactive protocol, you will not get an end-of-file from the server (it's just sitting there waiting for another command).

There are two ways you can address this. On the client, you can only read as much data as is available() so that your client does not block (or just read one byte at a time using read()). Additionally (though I haven't tested this), from your writer thread, you can close the OutputStream (instead of flushing it) when you're done writing your command. That should cause the server to be notified of the end of input, which will close its response stream. That in turn should signal an end-of-file to your InputStream.

Edit: I will note that ChannelInputStream does seem to try to only fill the buffer you provide with what is immediately available. However, this seems to be an undocumented implementation and I would not rely on it for correctness. Don't rely on sleeps in your code; pump data as it is available and when you're done writing commands, either explicitly send an "exit" command (depending on your CLI API) and/or close the output stream.

hierynomus commented 8 years ago

@ramakrishnagorrela Is your problem solved with the excellent explanation from @markspeters?

ramakrishnagorrela commented 8 years ago

Hi Hierynomus, Thank for your update, we have changed code to read stream with read() as well as available() but no luck. still i am facing same issue.

ramakrishnagorrela commented 8 years ago

Hi Hierynomus, we tried with basic example like real ssh console interactive, but still i am facing same issue(hanging at read method), please check following code snippet once.

import java.io.IOException; import java.io.InputStream; import java.io.OutputStream;

import net.schmizz.sshj.SSHClient; import net.schmizz.sshj.connection.channel.direct.Session; import net.schmizz.sshj.transport.verification.PromiscuousVerifier;

public class SSHJConnect {

public static void main(String[] args) throws Exception {
    SSHClient ssh = new SSHClient();
    ssh.addHostKeyVerifier(new PromiscuousVerifier());
    ssh.setConnectTimeout(90000);         
    ssh.connect("xx.xx.xx.xx",22);
    ssh.authPassword("xxxxxx", "xxxxx");

    Session session = ssh.startSession();

    if (session == null){
        throw new Exception("SSH channel is not opened properly");
    }

    final InputStream inputStream = session.getInputStream();
    OutputStream outputStream = session.getOutputStream();

    Thread t = new Thread() {
        public void run() {
            try {
                int read;
                while ((read = inputStream.read()) > -1) {
                    System.out.write(read);
                    System.out.flush();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    };

    t.start();

    session.allocateDefaultPTY();

    session.startShell();

    int read;
    // byte[] buf = new byte[4096];
    while ((read = System.in.read()) > -1) {
        outputStream.write(read);
        outputStream.flush();
    }

    if(inputStream != null) {
        inputStream.close();
    }

    if(outputStream != null) {
        outputStream.close();
    }

    if(ssh != null) {
        ssh.disconnect();
    }
}

}

Please help me out. Thanks, Ramakrishna.

hierynomus commented 8 years ago

Have a look at the RudimentaryPty example in the examples, that should give you some ideas.

2016-06-15 12:48 GMT+02:00 ramakrishnagorrela notifications@github.com:

Hi Hierynomus, we tried with basic example like real ssh console interactive, but still i am facing same issue(hanging at read method), please check following code snippet once.

import java.io.IOException; import java.io.InputStream; import java.io.OutputStream;

import net.schmizz.sshj.SSHClient; import net.schmizz.sshj.connection.channel.direct.Session; import net.schmizz.sshj.transport.verification.PromiscuousVerifier;

public class SSHJConnect {

public static void main(String[] args) throws Exception { SSHClient ssh = new SSHClient(); ssh.addHostKeyVerifier(new PromiscuousVerifier()); ssh.setConnectTimeout(90000); ssh.connect("xx.xx.xx.xx",22); ssh.authPassword("xxxxxx", "xxxxx");

Session session = ssh.startSession();

if (session == null){
    throw new Exception("SSH channel is not opened properly");
}

final InputStream inputStream = session.getInputStream();
OutputStream outputStream = session.getOutputStream();

Thread t = new Thread() {
    public void run() {
        try {
            int read;
            while ((read = inputStream.read()) > -1) {
                System.out.write(read);
                System.out.flush();
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
};

t.start();

session.allocateDefaultPTY();

session.startShell();

int read;
// byte[] buf = new byte[4096];
while ((read = System.in.read()) > -1) {
    outputStream.write(read);
    outputStream.flush();
}

if(inputStream != null) {
    inputStream.close();
}

if(outputStream != null) {
    outputStream.close();
}

if(ssh != null) {
    ssh.disconnect();
}

}

}

Please help me out. Thanks, Ramakrishna.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/hierynomus/sshj/issues/251#issuecomment-226152801, or mute the thread https://github.com/notifications/unsubscribe/AAHLo0F_w3Fg-5twgvm3X3fZ8Bh6vASSks5qL9hkgaJpZM4Iy0BI .