Java 如何使用JSch ChannelExec捕获远程输入
我写了一个程序,只在远程机器上运行一个命令,然后停止。有一个计划:Java 如何使用JSch ChannelExec捕获远程输入,java,jsch,Java,Jsch,我写了一个程序,只在远程机器上运行一个命令,然后停止。有一个计划: import com.jcraft.jsch.*; import java.io.*; public class JSchTest { private static String readString(String prompt) { if (prompt != null) { System.out.println(prompt); }
import com.jcraft.jsch.*;
import java.io.*;
public class JSchTest {
private static String readString(String prompt) {
if (prompt != null) {
System.out.println(prompt);
}
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String input = null;
try {
input = in.readLine();
} catch (IOException e) {
System.err.println(e);
}
return input;
}
private static boolean readBoolean(String prompt) {
while (true) {
String input = readString(prompt);
if (input.equalsIgnoreCase("Y") || input.equalsIgnoreCase("N")) {
return input.equalsIgnoreCase("Y");
} else {
System.out.println("Enter Y or N.");
}
}
}
public static void main(String[] args) throws Exception {
JSch jsch = new JSch();
Session session = jsch.getSession(readString("Login:"),
readString("Server:"), Integer.parseInt(readString("Port:")));
session.setUserInfo(
new UserInfo() {
@Override
public String getPassphrase() {
return readString("Passphrase:");
}
@Override
public String getPassword() {
return readString("Password:");
}
@Override
public boolean promptPassword(String message) {
return readBoolean(message);
}
@Override
public boolean promptPassphrase(String message) {
return readBoolean(message);
}
@Override
public boolean promptYesNo(String message) {
return readBoolean(message);
}
@Override
public void showMessage(String message) {
System.out.println(message);
}
}
);
session.connect();
ChannelExec channel = (ChannelExec)session.openChannel("exec");
InputStream in = channel.getInputStream();
channel.setCommand(readString("Command:"));
channel.connect();
byte[] buffer = new byte[1024];
int bytes;
do {
while (in.available() > 0) {
bytes = in.read(buffer, 0, 1024);
System.out.print(new String(buffer, 0, bytes));
}
} while (!channel.isClosed());
channel.disconnect();
session.disconnect();
}
}
当我使用只产生输出的命令时,这个程序运行良好,例如echo Hello
。但是当我试图传递一个命令时,比如readvar;您输入的echo:$VAR
我的程序正在无限循环中运行,因为通道未关闭,正在等待输入
好的,所以我得到了频道的输出流来编写输入
OutputStream out = channel.getOutputStream();
并使i/o循环如下所示:
while (true) {
while (in.available() > 0) {
bytes = in.read(buffer, 0, 1024);
System.out.print(new String(buffer, 0, bytes));
}
if (channel.isClosed()) {
break;
} else if (true /* channel.isWaitingForInput() */) {
String output = readString(null) + "\n";
out.write(output.getBytes());
out.flush();
}
}
但正如你所看到的,我不知道频道另一边发生了什么。是否有我现在必须提供的信息?因此,我的程序随时都在请求输入,即使不需要输入
因此,有一个问题-我如何知道何时必须传入通道的输入,或者,也许,我如何重写我的程序,使其不仅运行命令,而且在需要时(但在最后停止)为它们提供输入?通道保持打开状态,直到断开连接。当您发送退出命令并注销主机时,它甚至不会自动断开连接
您需要检查channel.getExitStatus>-1。在主机关闭会话之前,退出状态为-1(通常由用户键入“退出”触发)
一旦退出状态返回的不是-1,您可以选择处理退出状态(即,它是干净的退出,还是有错误)。之后,您需要自己断开通道:
Channel channel=session.openChannel("shell");
channel.setInputStream(System.in);
channel.setOutputStream(System.out);
channel.connect();
while (channel.getExitStatus() == -1){
try{Thread.sleep(1000);}catch(Exception e){System.out.println(e);}
}
channel.disconnect();
通过上面的循环,任何进入java控制台的标准输入都将被发送到通道,一旦用户发送“退出”,通道将断开连接
这里有一个工作示例:
另外,jcraft示例(当您“退出”时,它实际上不会关闭,但它是一个正常工作的示例) 通道保持打开状态,直到断开连接。当您发送退出命令并注销主机时,它甚至不会自动断开连接
您需要检查channel.getExitStatus>-1。在主机关闭会话之前,退出状态为-1(通常由用户键入“退出”触发)
一旦退出状态返回的不是-1,您可以选择处理退出状态(即,它是干净的退出,还是有错误)。之后,您需要自己断开通道:
Channel channel=session.openChannel("shell");
channel.setInputStream(System.in);
channel.setOutputStream(System.out);
channel.connect();
while (channel.getExitStatus() == -1){
try{Thread.sleep(1000);}catch(Exception e){System.out.println(e);}
}
channel.disconnect();
通过上面的循环,任何进入java控制台的标准输入都将被发送到通道,一旦用户发送“退出”,通道将断开连接
这里有一个工作示例:
另外,jcraft示例(当您“退出”时,它实际上不会关闭,但它是一个正常工作的示例) 查看我对这个问题的回答查看我对这个问题的回答