如何创建一个模拟SSH shell用户交互的bot?
问题描述:
我试图实现一个模拟用户在Java中的ssh控制台上写/读的用户。 我正在使用JSCH库来管理ssh连接。 这是从我开始的代码:如何创建一个模拟SSH shell用户交互的bot?
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
错了,我需要用的东西,机器人可以用它来发送一个字符串(命令行)和接收一个String(命令执行的结果),我应该使用什么类型的流来获取?
此外我注意到,如果我发送一个命令并在很多情况下使用System.out
作为输出流,则输出为空,因为(我对此几乎肯定),Java应用程序在命令执行产生结果之前终止。对于JSCH通道监听器“等到命令执行完成后”告诉什么是最佳做法,然后继续?我可以在命令执行后使用Thread.sleep(someTime)
,但由于显而易见的原因,我不太喜欢它。
答
考虑使用第三方的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。