Implementing SSH shell terminal in webapp using JSch

2

I am trying to implement a shell terminal in a webapp using websocket in spring. I am able to send a single command to the JSch "exec" channel and send the output back to the websocket.

Image

The problem I am having is:

  1. I am not able to retain the state of the shell like working directory, when I send a second command. How can I retain the previous state? I have tried using the same session but it does not work.

     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();
     }
    

    To send back to the websocket, in the controller I have :

    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);
    }
    
  2. I tried using the "shell" channel instead of "exec" which worked for getting the input and output through standard input and output stream but I could not get the real-time input and output from/back to the websocket and UI. I am not sure how to proceed from here. Any direction on where/what to look would be very helpful.

    Here is my code for the SSH terminal through standard input/output stream:

    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());
            }
        }
    }
    

    To send the command from the UI, I have the following:

    function sendCommand() {
        if (stompClient != null) {
            stompClient.send("/app/user", {}, JSON.stringify({'command': $("#command").val()}));
        }
    }
    
java
ssh
jsch
spring-websocket
java-websocket
asked on Stack Overflow Jan 19, 2021 by Dines G • edited Jan 26, 2021 by Martin Prikryl

1 Answer

2

If you want to implement an interactive shell, you have to use the "shell" channel, not the "exec" channel. The "exec" channel is intended for automating individual commands.

Some references:

answered on Stack Overflow Jan 19, 2021 by Martin Prikryl

User contributions licensed under CC BY-SA 3.0