Search code examples
javascriptnode.jssocketsxtermjs

xterm.js reconnect with same PWD


I am using xterm.js in my web project to have a terminal on the web page. Every time I refresh my page or reconnect socket when a socket connection is broken due to internet fluctuation from the client. The current PWD directory is lost and it falls to specified CWD directory which is user home in my case. So again I have to do cd where I was working.

How can I connect and remain at same PWD where I was last time before page refreshing or socket disconnect?

One of the things I tried is to store term object and connect through the same object when reconnecting if it is already present. Not deleting process and object in on WebSocket disconnect.

var http = require('http');
var express = require('express');
var app = express();
var expressWs = require('express-ws')(app);
var pty = require('node-pty');
var cors = require('cors');
app.use(cors());
app.options('*', cors());
var terminals = {}; //global terminals

function getUser(token) {
    return new Promise((resolve, reject) => {
      try {
        return http.get({
            host: '',
            path: '',
            headers: {'token': token}
        }, function(response) {
            // Continuously update stream with data
            var body = '';
            response.on('data', function(d) {
                body += d;
            });
            response.on('end', function() {
                return resolve(JSON.parse(body));
            });
        });
      } catch (err) {
        console.log('Api failed');
        console.log(err);
        reject;
      }
    })
}

app.ws('/terminals/:user_id', function (ws, req) {
  try {
    getUser(req.params.user_id) /* cheking with api if user exist in my database*/
      .then(user_info => {
        if(terminals[parseInt(req.params.user_id)]){
          var term = terminals[parseInt(req.params.user_id)];
        }else {
          var term = pty.spawn(process.platform === 'win32' ? 'cmd.exe' : 'bash', [], {
            name: 'xterm-color',
            cwd: cwd,
            env: process.env
          });
          terminals[parseInt(req.params.user_id)] = term;
        }

        term.on('data', function(data) {
          ws.send(data);
        });

        ws.on('message', function(msg) {
          term.write(msg);
        });

        ws.on('close', function () {
          // process.kill(term.pid);
          // delete terminals[parseInt(req.params.pid)];
          // delete logs[req.params.pid];
        });
      })
      .catch(err => {
      })
  } catch (err) {
      console.log('Terminal webSocket failed');
      console.log(err);
  }
});

app.listen(3000);

This is not working for me. This gets me connect only first time but when I refresh my page terminal does not connect with existing store object.

Also, this has a problem if the spawned process is killed by the system but it still remains in javascript object and script try to reconnect with same term object it will fail.

Any guidelines how to achieve reconnect with same PWD.

Details

OS version: Mac OS , xterm.js version: 2.2.3


Solution

  • This can be solved very easily by just updating the ~/.bashrc on server

    Putting below two line in ~/.bashrc file worked for me

    PROMPT_COMMAND+='printf %s "$PWD" > ~/.storepwd'
    [ -s ~/.lastdirectory ] && cd `cat ~/.lastdirectory`
    

    Ref Save last working directory on Bash logout