我需要使用sshj库通过ssh在远程服务器上执行一些命令序列.
我做
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());
Run Code Online (Sandbox Code Playgroud)
它抛出了我
net.schmizz.sshj.common.SSHRuntimeException:此会话通道全部用完
但我不能为每个命令重新创建会话,因为这个例子它将显示主目录列表,但不显示/ some/dir列表.
lam*_*ins 21
虽然很奇怪,但session只能使用一次.所以你必须每次都重置会话.
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());
Run Code Online (Sandbox Code Playgroud)
或者,如果要连接的shell支持分隔命令(并且情境允许),则可以执行此操作(bash示例):
session.exec("ls -l; <command 2>; <command 3>");
您可以考虑使用类似Expect的第三方库,它简化了远程服务的工作并捕获输出.这些库旨在执行一系列命令.您可以尝试以下一组很好的选项:
然而,当我即将解决类似问题时,我发现这些库相当陈旧.它们还引入了许多不需要的依赖项.所以我创建了自己的,并将其提供给其他人.它被称为ExpectIt.我的库的优点在项目主页上说明.你可以尝试一下.
以下是使用sshj与公共远程SSH服务进行交互的示例:
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();
}
Run Code Online (Sandbox Code Playgroud)
这是完整可行示例的链接.
这个问题很古老,但只是为了澄清,引用了Wiki https://github.com/hierynomus/sshj/wiki
会话对象不可重用,因此分别只能通过exec(),startShell()或startSubsystem()拥有一个命令/ shell /子系统。但是您可以通过单个连接启动多个会话。
在我们的例子中,我们将其放入一个函数中
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;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6733 次 |
| 最近记录: |