0

I am using J2ssh library to connect to a Unix machine, run a command and get the result using input stream. But the programs runs into loop while reading the input stream. I am able to get the result from the input steam, but the program struck there and not proceeding. Why is the program stuck in that loop?

Here is the source code,

public void loginAndCheckProcess(String hostName, String userName, String password, String port) {
        try {
            SshConnector con = SshConnector.createInstance();

            SocketTransport transport = new SocketTransport(hostName, 22);
            transport.setTcpNoDelay(true);
            SshClient client = con.connect(transport, userName);

            Ssh2Client ssh2 = (Ssh2Client) client;

            PasswordAuthentication pwd = new PasswordAuthentication();
            do {
                pwd.setPassword(password);
            } while (ssh2.authenticate(pwd) != SshAuthentication.COMPLETE && client.isConnected());

            String command = "ps -ef | grep " + port + '\n';
            if (client.isAuthenticated()) {
                SshSession session = client.openSessionChannel();
                session.startShell();
                session.getOutputStream().write(command.getBytes());
                InputStream is = session.getInputStream();
                Scanner br = new Scanner(new InputStreamReader(is));

                String line = null;
                int isRunning = 0;
                while (br.hasNextLine()) {
                    line = br.nextLine();
                    isRunning++;
                    System.out.println(line);
                }
                session.close();
            }
        } catch (SshException | IOException | ChannelOpenException ex) {
            Logger.getLogger(Authenticator.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

I tried to replace the above second while loop with the following loop but no luck,

try (Reader in = new InputStreamReader(is, "UTF-8")) {
                    for (;;) {
                        int rsz = in.read(buffer, 0, buffer.length);
                        if (rsz < 0)
                            break;
                        out.append(buffer, 0, rsz);
                    }
                }
                System.out.println(out);

And with the following loop, but no luck,

byte[] tmp = new byte[1024];
                while (is.available() > 0) {
                    int i = is.read(tmp, 0, 1024);
                    if (i < 0) {
                        break;
                    }
                    System.out.print(new String(tmp, 0, i));
                }
halfer
  • 19,824
  • 17
  • 99
  • 186
arunan
  • 922
  • 1
  • 17
  • 25
  • 1
    What's the problem? All of `java.io` is blocking. Your code reads the input until end of stream. What behaviour are you seeing that you aren't expecting? – user207421 Jul 29 '15 at 08:53
  • I expect the loop to end when there is no data – arunan Jul 29 '15 at 09:37
  • 1
    you may use timeout option for the socket. on timeout, your `read()` will throw `SocketTimeoutException`, which could be used to do what you want – mangusta Jul 29 '15 at 09:43
  • @mangusta Thank you so much. It worked. – arunan Jul 29 '15 at 10:02
  • @user2655966 Then you need to read the Javadoc. That loop terminates at end of stream, not 'when there is no data'. – user207421 Jul 30 '15 at 00:09

2 Answers2

1

At last I found the answer, thank you mangusta.

I have added timeout on the socket. It worked. I just added below line in the program,

transport.setSoTimeout(3000);
arunan
  • 922
  • 1
  • 17
  • 25
0

Your code will keep looping on the session InputStream until the session closes i.e. the InputStream returns EOF. As you used startShell method, this spawns an interactive shell so the session will continue and present a new prompt after your command has executed, awaiting another command.

You could add a call to exit in your command

String command = "ps -ef | grep " + port + ';exit\n';

Or you could use the alternative executeCommand method on the session rather than writing out the command to the OutputStream.

session.executeCommand(command);