Reputation: 987
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;
}
}
Upvotes: 1
Views: 4152
Reputation: 11
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.
Upvotes: 1
Reputation: 116878
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:
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.
Upvotes: 1