Jsch has some excellent examples in the examples directory, the one in particular you might find of interest is called Exec
. You might also be interested in Shell
This is a slightly modified version which skips getting the information from the command line and prompting for the user info and command and simply attempts to connect directly to the remote machine and execute a ls
command.
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.UserInfo;
import java.io.InputStream;
import java.util.Properties;
public class TestShell {
public static void main(String[] arg) {
try {
JSch jsch = new JSch();
Session session = jsch.getSession("username", "computer", 22);
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
// Skip prompting for the password info and go direct...
session.setPassword("happybunnyslippers");
session.connect();
String command = "ls";
Channel channel = session.openChannel("exec");
((ChannelExec) channel).setCommand(command);
((ChannelExec) channel).setErrStream(System.err);
InputStream in = channel.getInputStream();
System.out.println("Connect to session...");
channel.connect();
byte[] tmp = new byte[1024];
while (true) {
while (in.available() > 0) {
int i = in.read(tmp, 0, 1024);
if (i < 0) {
break;
}
System.out.print(new String(tmp, 0, i));
}
if (channel.isClosed()) {
System.out.println("exit-status: " + channel.getExitStatus());
break;
}
try {
Thread.sleep(1000);
} catch (Exception ee) {
}
}
channel.disconnect();
session.disconnect();
} catch (Exception e) {
System.out.println(e);
}
}
}
I tested this on my Windows box connecting to one of my Mac boxes without any issues
Updated with hacked Shell example
Basically, this is a hacked example based on the Shell
example.
This uses a custom OutputStream
to monitor changes to the content being sent from the remote machine and which can issue commands. This is pretty basic, in the fact that all I'm doing is waiting for $
to be send to the output stream and then issuing the next command.
It wouldn't take too much work to modify it so that, based on the current command/command index, you could do different parsing...
import com.jcraft.jsch.*;
import java.awt.*;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import javax.swing.*;
public class TestShell {
public static void main(String[] arg) {
try {
JSch jsch = new JSch();
String host = null;
final Session session = jsch.getSession("user", "remotecomputer", 22);
session.setPassword("fluffybunnyslippers");
session.setConfig("StrictHostKeyChecking", "no");
session.connect(30000); // making a connection with timeout.
final Channel channel = session.openChannel("shell");
PipedInputStream pis = new PipedInputStream();
final PipedOutputStream pos = new PipedOutputStream(pis);
channel.setInputStream(pis);
channel.setOutputStream(new OutputStream() {
private int cmdIndx = 0;
private String[] cmds = {
"ls\n",
"cd ..\n",
"ls\n",
"exit\n"
};
private String line = "";
@Override
public void write(int b) throws IOException {
char c = (char) b;
if (c == '\n') {
logout(line);
System.out.print(line);
line = "";
} else {
line += c;
logout(line);
if (line.endsWith("$ ")) {
String cmd = cmds[cmdIndx];
cmdIndx++;
pos.write(cmd.getBytes());
}
}
}
public void logout(String line) {
if (line.startsWith("logout")) {
System.out.println("...logout...");
channel.disconnect();
session.disconnect();
System.exit(0);
}
}
});
channel.connect(3 * 1000);
} catch (Exception e) {
System.out.println(e);
}
}
}