Taking the example provided by Mihail, other info on the internets, and the feedback from Martin, here's a reworked solution using exec
. Note that opening a session allows multiple commands to be sent, each one opening it's own channel for input/output.
Rant:I really dislike having to get the process' OUTPUT stream to write to. What an annoying paradigm (at least for me). What I wanted is the processes input stream to write my output to, and had an amazingly difficult time working out that it's inverted. Is it just me or does the following (pseudocode) not make way more sense??
channel.getInputStream().write("here's some text to write into my channel.");
String ret = channel.getOutputStream().getOutput();
Anyways, thanks to Mihail and Martin for their comments / input.
public class SSHConnectionManager {
private Session session;
private String username = "user";
private String password = "password";
private String hostname = "myhost";
public SSHConnectionManager() { }
public SSHConnectionManager(String hostname, String username, String password) {
this.hostname = hostname;
this.username = username;
this.password = password;
}
public void open() throws JSchException {
open(this.hostname, this.username, this.password);
}
public void open(String hostname, String username, String password) throws JSchException{
JSch jSch = new JSch();
session = jSch.getSession(username, hostname, 22);
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no"); // not recommended
session.setConfig(config);
session.setPassword(password);
System.out.println("Connecting SSH to " + hostname + " - Please wait for few seconds... ");
session.connect();
System.out.println("Connected!");
}
public String runCommand(String command) throws JSchException, IOException {
String ret = "";
if (!session.isConnected())
throw new RuntimeException("Not connected to an open session. Call open() first!");
ChannelExec channel = null;
channel = (ChannelExec) session.openChannel("exec");
channel.setCommand(command);
channel.setInputStream(null);
PrintStream out = new PrintStream(channel.getOutputStream());
InputStream in = channel.getInputStream(); // channel.getInputStream();
channel.connect();
// you can also send input to your running process like so:
// String someInputToProcess = "something";
// out.println(someInputToProcess);
// out.flush();
ret = getChannelOutput(channel, in);
channel.disconnect();
System.out.println("Finished sending commands!");
return ret;
}
private String getChannelOutput(Channel channel, InputStream in) throws IOException{
byte[] buffer = new byte[1024];
StringBuilder strBuilder = new StringBuilder();
String line = "";
while (true){
while (in.available() > 0) {
int i = in.read(buffer, 0, 1024);
if (i < 0) {
break;
}
strBuilder.append(new String(buffer, 0, i));
System.out.println(line);
}
if(line.contains("logout")){
break;
}
if (channel.isClosed()){
break;
}
try {
Thread.sleep(1000);
} catch (Exception ee){}
}
return strBuilder.toString();
}
public void close(){
session.disconnect();
System.out.println("Disconnected channel and session");
}
public static void main(String[] args){
SSHConnectionManager ssh = new SSHConnectionManager();
try {
ssh.open();
String ret = ssh.runCommand("ls -l");
System.out.println(ret);
ssh.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}