如何使用 JSch 执行交互式命令并从 Java 读取它们的稀疏输出
How to execute interactive commands and read their sparse output from Java using JSch
目前我可以使用 JSch 库在 SSH 会话中执行远程命令,如下所示:
JSch jsch = new JSch();
Session session = jsch.getSession(username, host, 22);
session.setPassword(password);
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect();
ChannelExec channel = (ChannelExec) session.openChannel("exec");
BufferedReader in = new BufferedReader(new InputStreamReader(channel.getInputStream()));
channel.setCommand("ls -l");
channel.connect();
StringBuilder output = new StringBuilder();
String s = null;
while((s = in.readLine()) != null){
output.append(s + "\n");
}
System.out.println(output);
立即 returns 完整值的命令工作正常,但一些交互式命令(如 "Docker run")returns 值大约每秒(几分钟) , 而前面的代码只读取返回的第一个值。
有什么方法可以读取命令返回的值吗?
编辑
现在这是我的代码:
public String executeCommand(String cmd) {
try {
Channel channel = session.openChannel("shell");
OutputStream inputstream_for_the_channel = channel.getOutputStream();
PrintStream commander = new PrintStream(inputstream_for_the_channel, true);
channel.setOutputStream(System.out, true);
channel.connect();
commander.println(cmd);
commander.close();
do {
Thread.sleep(1000);
} while(!channel.isEOF());
} catch(Exception e) {
e.printStackTrace();
}
return null;
}
JSch getInputStream
的实现方式,其 read
似乎 return -1
不仅在 session/channel 关闭时,而且在 session/channel 关闭时暂时没有输入数据。
您最好使用 channel.isClosed()
来测试 session/channel 是否已关闭。见 official Exec.java
example:
byte[] tmp=new byte[1024];
while(true){
while(in.available()>0){
int i=in.read(tmp, 0, 1024);
if(i<0)break;
System.out.print(new String(tmp, 0, i));
}
if(channel.isClosed()){
if(in.available()>0) continue;
System.out.println("exit-status: "+channel.getExitStatus());
break;
}
try{Thread.sleep(1000);}catch(Exception ee){}
}
您使用“shell”通道的代码在控制台上打印输出,因为您已通过以下方式指示它:
channel.setOutputStream(System.out, true);
您必须实现输出流才能写入字符串。参见 Get an OutputStream into a String
或者实际上,您应该能够使用与“exec”频道相同的代码。
目前我可以使用 JSch 库在 SSH 会话中执行远程命令,如下所示:
JSch jsch = new JSch();
Session session = jsch.getSession(username, host, 22);
session.setPassword(password);
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect();
ChannelExec channel = (ChannelExec) session.openChannel("exec");
BufferedReader in = new BufferedReader(new InputStreamReader(channel.getInputStream()));
channel.setCommand("ls -l");
channel.connect();
StringBuilder output = new StringBuilder();
String s = null;
while((s = in.readLine()) != null){
output.append(s + "\n");
}
System.out.println(output);
立即 returns 完整值的命令工作正常,但一些交互式命令(如 "Docker run")returns 值大约每秒(几分钟) , 而前面的代码只读取返回的第一个值。
有什么方法可以读取命令返回的值吗?
编辑
现在这是我的代码:
public String executeCommand(String cmd) {
try {
Channel channel = session.openChannel("shell");
OutputStream inputstream_for_the_channel = channel.getOutputStream();
PrintStream commander = new PrintStream(inputstream_for_the_channel, true);
channel.setOutputStream(System.out, true);
channel.connect();
commander.println(cmd);
commander.close();
do {
Thread.sleep(1000);
} while(!channel.isEOF());
} catch(Exception e) {
e.printStackTrace();
}
return null;
}
JSch getInputStream
的实现方式,其 read
似乎 return -1
不仅在 session/channel 关闭时,而且在 session/channel 关闭时暂时没有输入数据。
您最好使用 channel.isClosed()
来测试 session/channel 是否已关闭。见 official Exec.java
example:
byte[] tmp=new byte[1024];
while(true){
while(in.available()>0){
int i=in.read(tmp, 0, 1024);
if(i<0)break;
System.out.print(new String(tmp, 0, i));
}
if(channel.isClosed()){
if(in.available()>0) continue;
System.out.println("exit-status: "+channel.getExitStatus());
break;
}
try{Thread.sleep(1000);}catch(Exception ee){}
}
您使用“shell”通道的代码在控制台上打印输出,因为您已通过以下方式指示它:
channel.setOutputStream(System.out, true);
您必须实现输出流才能写入字符串。参见 Get an OutputStream into a String
或者实际上,您应该能够使用与“exec”频道相同的代码。