1

I am trying to run some unix commands from my java code. I am using Google's Expect4J library for now and am open to any well documented libraries out there.

The problem is I am trying to capture output of last run command but am not able to get it. Does anyone know, what I am doing wrong here ?

The problem I am trying to solve here is connect to my jumphost and then SSH to some other servers, based on if I am able to connect, I need to copy or run some scripts on target server.

The code I have written is pasted below. Please help !!!

import java.io.IOException;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;

import org.apache.oro.text.regex.MalformedPatternException;
import org.junit.internal.matchers.SubstringMatcher;

import com.jcraft.jsch.ChannelShell;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.bean.Server;

import expect4j.Closure;
import expect4j.Expect4j;
import expect4j.ExpectState;
import expect4j.matches.Match;
import expect4j.matches.RegExpMatch;

public class ExpectTest1 {

    public final String RETURN_CHAR = "\r ";
    public  String expectOut = "";

    private StringBuilder sBuilder = new StringBuilder();

    /**
     * @param args
     */
    public static void main(String[] args) {
        Expect4j exp;
        List<String> cmdsToRun = new ArrayList<String>(); 

        try {
            ExpectTest1 test = new ExpectTest1();
            exp = test.SSH("jumpbox.xyz.com","user1","passwd", cmdsToRun);
            exp.getLastState().toString();
        } catch (Exception e) {
            e.printStackTrace();
    }


}

    public Expect4j SSH(String hostname, String username, String password, List<String> cmdsToRun) throws Exception {
        return SSH(hostname, username, password, 22, cmdsToRun);
    }

    public Expect4j SSH(String hostname, String username, String password, int port, List<String> cmdsToRun) throws Exception {

    JSch jsch=new JSch();
    Session session=jsch.getSession(username, hostname, port);
    if( password != null) {
        session.setPassword(password);
    }

    Hashtable config=new Hashtable();
    config.put("StrictHostKeyChecking", "no");
    session.setConfig(config);
    session.setDaemonThread(true);
    session.connect(3 * 1000);   // making a connection with timeout.

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

    channel.setInputStream(System.in);
    channel.setOutputStream(System.out);

    channel.setPtyType("vt102");

    Expect4j expect = new Expect4j(channel.getInputStream(), channel.getOutputStream());

    channel.connect(5*1000);

    Server hostServer = new Server();
    hostServer.setHostName("box1.xyz.com");
    hostServer.setUsername("user2");

    Server destServer = new Server();
    destServer.setHostName("box2.xyz.com");
    destServer.setUsername("user3");

    boolean isLogged = doSSH(hostServer, expect);
    if(isLogged) {
        doSSH(destServer, expect);
    }

    return expect;
}

    private boolean doSSH (Server server, Expect4j expect) throws IOException, MalformedPatternException, Exception {
        String command = "ssh " + server.getUsername() + "@" + server.getHostName() + RETURN_CHAR;
        System.out.println("Logging in to: " + command);
        boolean logged;
        expect.send(command);
        Thread.sleep(4000);
        command = "uname -a" + RETURN_CHAR;
        System.out.println(command);
        expect.send(command);
        Thread.sleep(10000);

            if(isMatch(expect,server.getHostName().substring(0,server.getHostName().indexOf(".")))) {
            System.out.println("Logged in to:" + server.getHostName() + ".....");
            return true;
        }

        if(isMatch(expect, "Last login")) {
            System.out.println("Logged in to:" + server.getHostName() + ".....");
            return true;
        }

        if(isMatch(expect, "not known")) {
            System.out.println("Node or Service not known...");
            return false;
        }

        System.out.println("Node or Service not known...");
        return false;

        /*expect.expect(new Match[] {
            new RegExpMatch("Name or service not known", new Closure() {
                public void run(ExpectState state) throws Exception {
                    System.out.println("Name or service not known...");
                    expectOut = state.getBuffer();
            }
        })  
        });

        expect.expect( new Match[] {
                new RegExpMatch("Last login: \\w{3} (.*) from", new Closure() {
                    public void run(ExpectState state) throws Exception {
                        System.out.println("Logged In....");
                        expectOut = state.getBuffer();
                    }
                })
            });

        if(expectOut != null && expectOut.length()>0 && !expectOut.matches("Name or service not known")) 
            return true;

        return false;*/

    }

    private boolean isMatch(Expect4j expect, String regEx) throws MalformedPatternException, Exception {
        /*expect.expect( new Match[] {
                new RegExpMatch(regEx, new Closure() {
                    public void run(ExpectState state) throws Exception {
                        System.out.println(state.getBuffer());
                        System.out.println(state.getMatch());
                        expectOut = state.getMatch();
                        //System.out.println(state.getMatch());
                    }
                })
            });

        if(expectOut != null 
                && expectOut.length()>0 
                && expectOut.matches(regEx)) {
            //System.out.println(regEx);
            return true;
        }*/
        System.out.println("*************");
        System.out.println(expect.expect(regEx));
        System.out.println("*************");
        if(expect.expect(regEx) == 0)
            return true;

        return false;
    }

}

0

2 Answers 2

1

I suspect that your ssh command is trying to prompt for a password or trying to ask you to add the host key to the `known_hosts file. I'm not sure they can be done by Expect4j since ssh connects to the tty directly to ask those questions. But this answer seems to have solved it:

Using expect to pass a password to ssh

Here's a similar question/answers that may help:

How to make a ssh connection to a firewall(router) with java?

When I am automating my ssh connections, I use public/private key encryption instead of passwords to connect to the server and I make sure that the server has been connected from the client from the command line successfully without a password. Make sure that the full host name is used. This will save the host key to the `known_hosts file so it won't be prompted for in the future.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the answer. I have already setup password less entries from jumphost to server1 and from server1 to server2. It is actually able to SSH to the servers, the problem is when I pass a non existent server name. The code still recognize that we have logged on to the server !!
1

Just an idea, you might consider using a Java library that handles the expect and key management for you. Here is one that I found which seems to do the trick.

http://www.jscape.com/products/components/java/ssh-factory/

See the SshScript or SshSession classes and documentation for details.

1 Comment

Yes, Jscape works fine as I had used it earlier. Only problem is its a paid library, which the management is not really interested in (at-least as of now).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.