2

I am in a trouble while coding ssh2 module in my project. I tried to run multiple commands on one terminal for ruling remote Linux system. For example "bc" command provides you a basic calculator and you can run it for basic operations. but that kind of processes need to be awake when you are using (it will accepts two or more input and it will give a response as a result).

I need to create a system like work with websocket and ssh. When a websocket received a command ,ssh node need to execute this message and Module need to send it's response via websocket.send()

I am using Node.js websocket,ssh2 client.

Here my code :

#!/usr/bin/node
var Connection = require('ssh2');
var conn = new Connection();

var command="";
var http = require('http');
var WebSocketServer = require('websocket').server;
var firstcom=true;
conn.on('ready', function() {
                console.log('Connection :: ready');
               // conn.shell(onShell);

            }); 

var onShell = function(err, stream) { 

                  //  stream.write(command+'\n');

                    stream.on('data', function(data) {
                        console.log('STDOUT: ' + data);
                    });

                    stream.stderr.on('data', function(data) {
                    console.log('STDERR: ' + data);

                   });

          }



var webSocketsServerPort=5000;
var ssh2ConnectionControl=false;

var server = http.createServer(function (req, res) {
  //blahbalh
}).listen(webSocketsServerPort, function() {
    console.log((new Date()) + " Server is listening on port:: " + webSocketsServerPort);
});

//console.log((new Date()) + 'server created');

wsServer = new WebSocketServer({
    httpServer: server,
 //   autoAcceptConnections: false
});

wsServer.on('request', function(request) {
    console.log((new Date()) + ' Connection from origin ' + request.origin + '.');
    var wsconnection = request.accept('echo-protocol', request.origin);
    console.log((new Date()) + ' Connection accepted.');

    if(!ssh2ConnectionControl){
      conn.connect({
                host: 'localhost',
                port: 22,
                username: 'attilaakinci',
                password: '1'
              });
      ssh2ConnectionControl=true;
        console.log('SSH Connected.');       
    } 

    wsconnection.on('message', function(message) {
        if (message.type === 'utf8') {
            console.log('Received Message: ' + message.utf8Data);
            command=message.utf8Data;

            //if(firstcom){
            //  conn.shell(onShell);
            //  firstcom=false;
            //}else{
              conn.exec(message.utf8Data,onShell);

            //}

            wsconnection.send(message.utf8Data);
        }
        else{
            console.log('Invalid message');
        }
    });

    wsconnection.on('close', function(reasonCode, description) {
        console.log((new Date()) + ' Peer ' + wsconnection.remoteAddress + ' disconnected.');
    });
});
1
  • This code is executing commands on different shell I realized that situation when I checked terminal process id. so I lose the usage of the ssh connection. I need to execute them on same terminal. Please help me about that problem. Thanks a lot.. Commented Jul 25, 2014 at 12:53

2 Answers 2

3

You should use conn.shell() instead of conn.exec() if you want a real interactive shell. conn.exec() is typically for executing one-liner commands, so it does not persist "shell state" between conn.exec() calls (e.g. working directory, etc.).

You should also be aware of possible limits by your SSH server has set up as far as how many simultaneous shell/exec requests are allowed per connection. I think the default limit for this on OpenSSH's server is 10.

Sign up to request clarification or add additional context in comments.

7 Comments

I tried that method too. When I use shell command every command executes on different terminals and I lose the ongoing process. I found a explanation and it says shell command starts an interactive shell session on the server. I need to do that in one shell session. shell command explanation on github
The problem with sharing a single interactive shell session is that you will mix input/output from other websocket connections. Is that really what you want? That could cause problems if a websocket message does not contain an entire command. Even then you could still get unexpected behavior with output.
For something like bc you could keep the conn.exec() stream associated with the websocket connection and just keep writing to and reading from that stream because bc is an interactive program (until you explicitly quit).
hi mscdex, i tried your tip to run this command on my remote m/c - "sudo su\nwhoami\n" with conn.shell. It started printing the shell prompt on my nodejs console (like this - [cloud-user@host-10-199-17-26 ~]$ ) which is really ugly & again, 'end' event didn't get raised for the stream.... With conn.exec, the stream events were getting raised properly, only that one command's changes were not visible to others.
@MadhavanKumar Yep, that's the nature of the ssh2 protocol, there's not really anything I can do about that. If you just need to keep track of the cwd, you could write a wrapper class that keeps track of it manually using the path module and/or realpath on the server.
|
1

This is an old question but I wanted to provide a alternative method usings sh2shell which wraps ssh2.shell by mscdex, used above. The example below only covers making the ssh connection, running the commands and processing the result.

Using ssh2shel it is possible to run any number of commands sequentually in the context of the previous commands in the same shell session and then return the output for each command (onCommandComplete event) and/or return all session text on disconnection using a callback function. See the ssh2shell readme for examples and lots of info. There are also tested scripts for working code examples.

var host = {
    //ssh2.client.connect options
    server: {     
        host:         120.0.0.1,
        port:         22,
        userName:     username,
        password:     password
    },
    debug:          false,
    //array of commands run in the same session
    commands:       [
        "echo $(pwd)",
        command1,
        command2,
        command3
    ],      
    //process each command response
    onCommandComplete:   function( command, response, sshObj) {
        //handle just one command or do it for all of the each time
        if (command === "echo $(pwd)"){      
            this.emit("msg", response);
        }
    }
};

//host object can be defined earlier and host.commands = [....] set repeatedly later with each reconnection.

var SSH2Shell = require ('ssh2shell');

var SSH = new SSH2Shell(host),
    callback = function( sessionText ){
        console.log ( "-----Callback session text:\n" + sessionText);
        console.log ( "-----Callback end" );
    }

SSH.connect(callback)

To see what is happening at process level set debug to true.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.