我正在使用Jsch库在少数linux机器上执行大约1000种不同的shell脚本,并将状态更新为表格。
我使用了jsch exec channel [ChannelExec],它只适用于单个脚本,如果shell脚本调用另一个脚本,则ChannelExec没有给出正确的结果。
现在我正在使用jsch的shell channnel。它可以很好地从任何类型的shell脚本中获取输出。
问题是,如果我一次执行多个shell脚本,我将获得所有结果。
无法执行一个Shell脚本并收到其结果。
如果我想获得单个脚本执行结果,我需要为每个脚本执行登录到机器,这需要很长时间。
有人可以发布解决方案,建议如何进行,登录一次机器并执行多个脚本并单独接收每个脚本结果。
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
public class JschShellExample {
public static void main(String[] args) {
try {
JSch jsch = new JSch();
Session session = jsch.getSession("user", "10.32.248.158", 22);
session.setPassword("password");
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
config.put("PreferredAuthentications","publickey,keyboard-interactive,password");
session.setConfig(config);
session.connect(100);
Channel channel = session.openChannel("shell");
OutputStream inputstream_for_the_channel = channel.getOutputStream();
PrintStream commander = new PrintStream(inputstream_for_the_channel, true);
channel.setOutputStream(null);
channel.connect(100);
//shell script
commander.println("cd /user/home/work ; ./checkstaus.sh ; exit");
commander.flush();
System.out.println(channel.getExitStatus());
InputStream outputstream_from_the_channel = channel.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(outputstream_from_the_channel));
String line = null;
StringBuilder sb = new StringBuilder();
boolean isloginStringPassed = false ;
while ((line = br.readLine()) != null) {
sb.append(line.trim());
}
System.out.println("Result ="+sb.toString());
channel.disconnect();
session.disconnect();
System.out.println("completed .. ");
} catch (JSchException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
答案 0 :(得分:0)
通常当您第一次连接到远程计算机并执行命令后,您将在输出流中打印shell command line prompt。您可以将它用作不同shell命令输出之间的标记。
您可以考虑使用Expect-like第三方库,它简化了远程服务的工作并捕获输出。你可以尝试一系列很好的选择:
然而,当我即将解决类似的问题时,我发现这些库相当陈旧,难以在商业软件中使用。所以我创建了自己的,并将其提供给其他人。它叫ExpectIt。我的库的优点在project home page上说明。
以下是与公共远程SSH服务进行交互的示例:
JSch jSch = new JSch();
Session session = jSch.getSession("new", "sdf.org");
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect();
Channel channel = session.openChannel("shell");
Expect expect = new ExpectBuilder()
.withOutput(channel.getOutputStream())
.withInputs(channel.getInputStream(), channel.getExtInputStream())
.withEchoOutput(adapt(System.out))
// .withInputFilters(removeColors(), removeNonPrintable())
.withErrorOnTimeout(true)
.build();
// try-with-resources is omitted for simplicity
channel.connect();
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(": $"));
// finally is omitted
channel.disconnect();
session.disconnect();
expect.close();
您还可以查看一个与卡拉夫外壳交互的this示例,该外壳可捕获单个命令输出。