0

I am following below steps for running commands on ssh server.

  1. Connecting to ssh server
  2. Using devpush command again logging to server (using expectit library for user input prompt).
  3. Finally running remote commands using jsch library.

The issue I am facing is that, my code is going in infinite loop it is able to login to ssh server but not able to run the commands. Can any one please help me on this as I am using both the libraries for first time.

package com.dmotorworks.cdk;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import net.sf.expectit.*;
import net.sf.expectit.matcher.Matchers;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;

public class ShellClient {

    public void loginToPabloServer() throws IOException, JSchException{
        String hostname="pablo.dmotorworks.com";
        String username="gaikwasu";
        String password="Nexus@80900";
        final String  endLineStr=" # ";

        JSch jsch = new JSch();     
        Session session = jsch.getSession(username, hostname, 22);
        session.setPassword(password);
        jsch.setKnownHosts("C://Users//gaikwasu//.ssh//known_hosts");

        session.connect();
        System.out.println("Connected");


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

        Expect expect=new ExpectBuilder()
                .withOutput(channel.getOutputStream())
                .withInputs(channel.getInputStream(), channel.getExtInputStream())
                .withEchoOutput(System.out)
                .withEchoInput(System.err)
                .withExceptionOnFailure()
                .build();

        expect.expect(Matchers.contains("-bash-4.1$"));    
        expect.send("devpush\n");
        expect.expect(Matchers.contains("[sudo] password for"));
        expect.send(password+"\n");


        DataInputStream dataIn = new DataInputStream(channel.getInputStream());
        DataOutputStream dataOut = new DataOutputStream(channel.getOutputStream());
        BufferedReader bufferReader= new BufferedReader(new InputStreamReader(dataIn));

        dataOut.writeBytes("cd custom\n");
        dataOut.writeBytes("ls -lrt\n");
        dataOut.flush();

        String line=bufferReader.readLine();
        while(!line.endsWith(endLineStr)) {
               System.out.println(line);
          }

        channel.disconnect();
        session.disconnect();
        expect.close();


    }

    public static void main(String[] args) {
        ShellClient shellClient=new ShellClient();
        try {
            shellClient.loginToPabloServer();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (JSchException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
Alexey Gavrilov
  • 10,593
  • 2
  • 38
  • 48

1 Answers1

0

Most probably the cause of the infinitive loop is because the Expect instance reads the input data in a separate thread at the same time while you are trying to same data in the main thread.

Try to close the Expect instance before reading the data. It may help.

However, I strongly recommend to keep using the Expect instance after the sending password. ExpectIt can help with extracting the information from the remote command output. For example:

    expect.sendLine(password);
    expect.expect(Matchers.contains("-bash-4.1$"));
    expect.sendLine("cd custom");
    expect.expect(Matchers.contains("-bash-4.1$"));
    expect.sendLine("ls -lrt");
    // the lsResult variable should contain the result of the 'ls -l' command
    String lsResult = expect.expect(Matchers.contains("-bash-4.1$")).getBefore();
    System.out.println(lsResult);

Please take a look at this example.

Alexey Gavrilov
  • 10,593
  • 2
  • 38
  • 48
  • Please comment your codes. Will be easy to us to understand. How can I get the console output? – Magno C Jul 17 '15 at 00:47
  • The `getBefore` method returns the console output before the match. The `lsResult` variable should contain the result of the `ls -l` command, – Alexey Gavrilov Jul 17 '15 at 12:56
  • Thanks Alexey. I'm having trouble to implement a `sudo -i`. I'll start a new question. Can you give a look? http://stackoverflow.com/questions/31477489/expectit-trouble-implementing-a-sudo-i – Magno C Jul 17 '15 at 13:53