我试图实现一个模拟用Java编写/读取ssh控制台的用户的机器人。 我正在使用JSCH库来管理ssh连接。 这是我开始的代码:
JSch jsch = new JSch();
Session session = jsch.getSession(username, ipAddress, port);
session.setPassword(password);
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect(connectionTimeoutInMillis);
Channel channel = session.openChannel("shell");
InputStream is = new InputStream();
OutputStream out= new OutputStream();
channel.setInputStream(is);
channel.setOutputStream(out);
channel.connect();
channel.disconnect();
is.close();
out.close();
session.disconnect();
显然代码中的InputStream
和OutputStream
是错误的,我需要使用机器人可以用来发送字符串(命令行)并接收字符串(结果为命令执行),我应该用什么类型的流来获取它?
此外我注意到,如果我发送命令并在许多情况下使用System.out
作为输出流,则输出为空,因为(我几乎可以肯定这一点)Java应用程序在命令之前终止执行产生了结果。告诉JSCH通道监听器" 等待命令执行完成的最佳做法是什么"然后继续?在命令执行后我可以使用Thread.sleep(someTime)
,但由于显而易见的原因,我不太喜欢它。
答案 0 :(得分:1)
考虑使用第三方Expect-like Java库来简化与远程shell的交互。您可以尝试以下一组很好的选项:
您还可以查看我之前创建的自己的开源项目,作为现有项目的继承者。它被称为ExpectIt。我的库的优点在项目主页上说明。
以下是使用JSch与公共远程SSH服务进行交互的示例。根据您的使用情况应该很容易采用它。
JSch jSch = new JSch();
Session session = jSch.getSession("new", "sdf.org");
session.connect();
Channel channel = session.openChannel("shell");
Expect expect = new ExpectBuilder()
.withOutput(channel.getOutputStream())
.withInputs(channel.getInputStream(), channel.getExtInputStream())
.withErrorOnTimeout(true)
.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();
}
以下是指向完整可行的example。
的链接