ssh persistent sessions with node.js

2019-08-14 03:11发布

问题:

I am working with node.js, and I am trying to embed a console in the web browser to work in a remote server. The web application do the connection so the user does not need to do the ssh username@host but only type commands.

I have tried the node.js' ssh2 module and other modules which use ssh2. But I'm experiencing always the same problem. Every time I execute a command programmatically using exec(), the ssh session is restarted. I'll explain it better with an example.

> ls

returns the content of home directory, one of the directories in the home directory is mydir

> cd mydir
> ls

returns the content of my home directory again, because after a command is executed the ssh session is closed/restarted.

Any node.js library which can do the job? or even a library of other technology different to javascript?

Edit: Other example for clarifying, using the node.js' module ssh-exec The server has to execute some commands in other machine using ssh. A function in the server contains the following code

var c = exec.connection('username@host.com'); // It takes the ssh key from the default location
exec('cd mydir', c).pipe(process.stdout);
exec('ls -lh', c).pipe(process.stdout);

As you can see I am not ending the connection after the first exec but the output I obtain is the content of the home directory not the content of mydir directory, because the ssh session is reset after each exec.

回答1:

The maintainer of node.js' ssh2 module provided the solution.

To use the method shell() instead of the method exec().

The method shell() creates an interactive session with the server we are connecting. The method shell() provides a stream as a parameter of its callback (like the method exec()).

Like when using exec(), stream.on('data', function(data, extended) {...}); can be used to get the output of the commands. However, in this case, to provide commands (input) to the machine you connected with, you need to use stream.write(yourcommand+'\n');

PS. Feel free to edit to improve the accuracy of the answer.



回答2:

I have to guess a bit, but you do something like child = exec('ssh username@host ls')?

You can do something like

child = exec('ssh username@host');

upfront and in the "loop" of your browser

child.stdin.write('ls\n');

When finished, just close stdin:

child.stdin.end()

which also finishes the child process.



回答3:

I know this link is old but I figured this may help someone if they're looking for a solution. The

To use the method shell() instead of the method exec().

Works. Here's another solution. Use absolute file paths i.e.

conn.exec("mkdir -p /home/user/Direc/{one,two,three}/", function(err, stream) {
        if (err) throw err;
        stream.on('data', function(data) {
            console.log('STDOUT: ' + data);
        }).stderr.on('data', function(data) {
            console.log('STDERR: ' + data);
        });
    });

conn.exec("ls -la /home/user/", function(err, stream) {
    if (err) throw err;
    stream.on('close', function(code, signal) {
        console.log('Stream :: close :: code: ' + code + ', signal: ' + signal);
        conn.end();
    }).on('data', function(data) {
        console.log('STDOUT: ' + data);
    }).stderr.on('data', function(data) {
        console.log('STDERR: ' + data);
    });
});