简体   繁体   中英

Node SSH2 client connection session

I want to setup an SSH-connection to a device using Node.js. The goal is to connect and keep the connection for a longer time, instead of connecting and disconnecting over and over again.

I was able to setup a connection but a problem arises when my callbacks are getting called multiple times. The callbacks are used to answer GET-requests from my frontend and when the callback fire multiple time the response header gets filled a second time and I get an error.

Is there a more elegant way to build up a long lasting connection while avoiding multiple callbacks?

const { Client } = require('ssh2');

var connection;
var connEstablished = false;


var connect = (callback) => {
    const conn = new Client();
    conn.on('ready', () => {
        callback(null, true);
        connection = conn;
        connEstablished = true;
        console.log("Connection ready");
    }).connect({
        host: '192.168.1.1',
        port: 22,
        username: 'pi',
        password: 'raspberry',
        readyTimeout: 2000,
        keepaliveInterval: 500
    });
    conn.on('end', () => {
        callback(null, false);
        connection = null;
        connEstablished = false;
        console.log("Connection end");
    })
    conn.on('error', (error) => {
        callback(error, false);
        connection = null;
        connEstablished = false;
        console.error("SSH Client Error: ", JSON.stringify(error));
    })
};

var disconnect = () => {
    if (!connEstablished) {
        return;
    }

    connection.end();
}

var command = (command) => {
    if (!connEstablished) {
        return;
    }

    connection.exec(command, (err, stream) => {
        if (err) {
            callback(err);
            return;
        }
        stream.on('data', (data) => {
            callback(null, data);
        }).stderr.on('data', (data) => {
            callback(null, data);
        });
    });
}

The problem is that you're making assumptions about the number of 'data' events emitted by a stream. For streams in general, you should never make such assumptions.

I suggest always coding defensively for streams as if you may get 1 byte at a time or you may get the entirety of the data you're looking for in a single event.

To fix this problem you will need to know when you have all of the data, which is entirely dependent upon the command(s) you are executing. For many commands it's most likely when the 'close' event is emitted to indicate there will be no more output for that stream (the process has exited). However for some long-running processes where you send multiple requests over the lifetime of the remote process, you will need to find a way to find the end of each "response" in the stream's output.

Either way, you will need to buffer the data until you see the end of the "response" before you execute your callback.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM