I need to execute some sequence of commands at the remote server via ssh, using sshj library.
I do
Session session = ssh.startSession();
Session.Command cmd = session.exec("ls -l");
System.out.println(IOUtils.readFully(cmd.getInputStream()).toString());
cmd.join(10, TimeUnit.SECONDS);
Session.Command cmd2 = session.exec("ls -a");
System.out.println(IOUtils.readFully(cmd2.getInputStream()).toString());
and it throws me
net.schmizz.sshj.common.SSHRuntimeException: This session channel is all used up
But I can't recreate session for every single command, because this example it will show home directory list, but not the /some/dir list.
You can consider using an Expect-like third party library which simplifies working with remote services and capturing output. Those libraries are designed to execute a sequence of commands. Here is a good set of options you can try:
However, when I was about to solve similar problem I found these libraries are rather old. They also introduce a lot of unwanted dependencies. So I created my own and made it available for others. It is called ExpectIt. The advantages of my library it are stated on the project home page. You can give it a try.
Here is an example of interacting with a public remote SSH service using sshj:
SSHClient ssh = new SSHClient();
...
ssh.connect("sdf.org");
ssh.authPassword("new", "");
Session session = ssh.startSession();
session.allocateDefaultPTY();
Shell shell = session.startShell();
Expect expect = new ExpectBuilder()
.withOutput(shell.getOutputStream())
.withInputs(shell.getInputStream(), shell.getErrorStream())
.build();
try {
expect.expect(contains("[RETURN]"));
expect.sendLine();
String ipAddress = expect.expect(regexp("Trying (.*)\\.\\.\\.")).group(1);
System.out.println("Captured IP: " + ipAddress);
expect.expect(contains("login:"));
expect.sendLine("new");
expect.expect(contains("(Y/N)"));
expect.send("N");
expect.expect(regexp(": $"));
expect.send("\b");
expect.expect(regexp("\\(y\\/n\\)"));
expect.sendLine("y");
expect.expect(contains("Would you like to sign the guestbook?"));
expect.send("n");
expect.expect(contains("[RETURN]"));
expect.sendLine();
} finally {
session.close();
ssh.close();
expect.close();
}
Here is the link to the complete workable example.
As odd as it is, session
can only be used once. So you have to reset the session every time.
Session session = ssh.startSession();
Session.Command cmd = session.exec("ls -l");
System.out.println(IOUtils.readFully(cmd.getInputStream()).toString());
cmd.join(10, TimeUnit.SECONDS);
session = ssh.startSession();
Session.Command cmd2 = session.exec("ls -a");
System.out.println(IOUtils.readFully(cmd2.getInputStream()).toString());
Or if the shell you are connecting to supports delimited commands (and the situation allows it), you can do this (bash example):
session.exec("ls -l; <command 2>; <command 3>");
This question is old but just to clarify, quoting from the wiki https://github.com/hierynomus/sshj/wiki
Session objects are not reusable, so you can only have one command/shell/subsystem via exec(), startShell() or startSubsystem() respectively. But you can start multiple sessions over a single connection.
In our case we have made put it in a function
public String runCmd(SSHClient sshClient, String command) throws IOException {
String response = "";
try (Session session = sshClient.startSession()) {
final Command cmd = session.exec(command);
response = (IOUtils.readFully(cmd.getInputStream()).toString());
cmd.join(5, TimeUnit.SECONDS);
// System.out.println("\n** exit status: " + cmd.getExitStatus());
}
return response;
}
来源:https://stackoverflow.com/questions/22723538/execute-sequense-of-commands-in-sshj