使用 JSch 在 webapp 中实现 SSH shell 终端
Implementing SSH shell terminal in webapp using JSch
我正在尝试在 spring 中使用 websocket 在 webapp 中实现一个 shell 终端。我能够将单个命令发送到 JSch“exec”通道并将输出发送回 websocket。
我遇到的问题是:
当我发送第二个命令时,我无法保留 shell 等工作目录的状态。我怎样才能保持以前的状态?我试过使用相同的会话,但它不起作用。
public String sendCommand(String command) {
StringBuilder outputBuffer = new StringBuilder();
try {
Channel channel = sesConnection.openChannel("exec");
((ChannelExec) channel).setCommand(command);
InputStream commandOutput = channel.getInputStream();
channel.connect();
int readByte = commandOutput.read();
while (readByte != 0xffffffff) {
outputBuffer.append((char) readByte);
readByte = commandOutput.read();
}
channel.disconnect();
} catch (IOException ioX) {
logWarning(ioX.getMessage());
return null;
} catch (JSchException jschX) {
logWarning(jschX.getMessage());
return null;
}
return outputBuffer.toString();
}
要发送回 websocket,在控制器中我有:
private SSHManager getSSHInstance() {
String errorMessage = null;
if (sshInstance == null) {
sshInstance = new SSHManager(username, password, host, "", port);
errorMessage = sshInstance.connect();
System.out.println("Instance created");
if (errorMessage != null) {
throw new RuntimeException("Could not create an ssh connection");
}
}
System.out.println("Returning created instance");
return sshInstance;
}
@MessageMapping("/user")
@SendTo("/topic/user")
public UserResponse getResponse(String command) {
SSHManager currInstance = getSSHInstance();
String result = currInstance.sendCommand(command);
return new UserResponse(result);
}
我尝试使用“shell”通道而不是“exec”,它可以通过标准输入和输出流获取输入和输出,但我无法实时获取输入和输出 from/back 到 websocket 和 UI。我不确定如何从这里开始。 where/what 上的任何方向都会很有帮助。
这是我通过标准 input/output 流的 SSH 终端代码:
import com.jcraft.jsch.*;
public class Terminal{
public static void main(String[] args){
try{
JSch jsch=new JSch();
String host = "127.0.0.1";
String user = "user";
String password = "pass";
Session session=jsch.getSession(user, host, 5679);
session.setPassword(password);
session.setConfig("StrictHostKeyChecking", "no");
session.connect(10000);
Channel channel=session.openChannel("shell");
channel.setInputStream(System.in);
channel.setOutputStream(System.out);
channel.connect(3*1000);
}
catch(Exception e){
System.out.println(e.getMessage());
}
}
}
要从 UI 发送命令,我有以下内容:
function sendCommand() {
if (stompClient != null) {
stompClient.send("/app/user", {}, JSON.stringify({'command': $("#command").val()}));
}
}
如果要实现交互式 shell,则必须使用“shell”频道,而不是“exec”频道。 “exec”通道用于自动执行单个命令。
一些参考资料:
- What is the difference between the 'shell' channel and the 'exec' channel in JSch
- JSch
Shell.java
example
我正在尝试在 spring 中使用 websocket 在 webapp 中实现一个 shell 终端。我能够将单个命令发送到 JSch“exec”通道并将输出发送回 websocket。
我遇到的问题是:
当我发送第二个命令时,我无法保留 shell 等工作目录的状态。我怎样才能保持以前的状态?我试过使用相同的会话,但它不起作用。
public String sendCommand(String command) { StringBuilder outputBuffer = new StringBuilder(); try { Channel channel = sesConnection.openChannel("exec"); ((ChannelExec) channel).setCommand(command); InputStream commandOutput = channel.getInputStream(); channel.connect(); int readByte = commandOutput.read(); while (readByte != 0xffffffff) { outputBuffer.append((char) readByte); readByte = commandOutput.read(); } channel.disconnect(); } catch (IOException ioX) { logWarning(ioX.getMessage()); return null; } catch (JSchException jschX) { logWarning(jschX.getMessage()); return null; } return outputBuffer.toString(); }
要发送回 websocket,在控制器中我有:
private SSHManager getSSHInstance() { String errorMessage = null; if (sshInstance == null) { sshInstance = new SSHManager(username, password, host, "", port); errorMessage = sshInstance.connect(); System.out.println("Instance created"); if (errorMessage != null) { throw new RuntimeException("Could not create an ssh connection"); } } System.out.println("Returning created instance"); return sshInstance; } @MessageMapping("/user") @SendTo("/topic/user") public UserResponse getResponse(String command) { SSHManager currInstance = getSSHInstance(); String result = currInstance.sendCommand(command); return new UserResponse(result); }
我尝试使用“shell”通道而不是“exec”,它可以通过标准输入和输出流获取输入和输出,但我无法实时获取输入和输出 from/back 到 websocket 和 UI。我不确定如何从这里开始。 where/what 上的任何方向都会很有帮助。
这是我通过标准 input/output 流的 SSH 终端代码:
import com.jcraft.jsch.*; public class Terminal{ public static void main(String[] args){ try{ JSch jsch=new JSch(); String host = "127.0.0.1"; String user = "user"; String password = "pass"; Session session=jsch.getSession(user, host, 5679); session.setPassword(password); session.setConfig("StrictHostKeyChecking", "no"); session.connect(10000); Channel channel=session.openChannel("shell"); channel.setInputStream(System.in); channel.setOutputStream(System.out); channel.connect(3*1000); } catch(Exception e){ System.out.println(e.getMessage()); } } }
要从 UI 发送命令,我有以下内容:
function sendCommand() { if (stompClient != null) { stompClient.send("/app/user", {}, JSON.stringify({'command': $("#command").val()})); } }
如果要实现交互式 shell,则必须使用“shell”频道,而不是“exec”频道。 “exec”通道用于自动执行单个命令。
一些参考资料:
- What is the difference between the 'shell' channel and the 'exec' channel in JSch
- JSch
Shell.java
example