I\'m using the below code to reset a password on a linux box using nodejs and ssh2 module:
// FILE * ./workflow/ssh.js
var Client = require(\'ssh2\').Client
As I have studied NodeJs in just recent times I agree this is late for the answer, I am building a monitoring tool and using the SSH-2 library of node.js to get the tasks done. Capturing the value in response for the API was troublesome but I thought to create the operations as Promise to capture then in Api call. I hope the below code will help.
//Operations file that I am calling from the API
var Poperation = (params)=>{
return new Promise((resolve, reject) => {
let result = "";
conn
.on("ready", function () {
conn.exec(params["command"], function (err, stream) {
if (err) {
reject(err);
};
stream
.on("close", function (code, signal) {
conn.end();
//callback(null, result);
resolve(result)
})
.on("data", function (data) {
result = data;
})
.stderr.on("data", function (data) {
});
});
})
.connect({
host: params["host"],
port: params["port"],
username: params["username"],
password: params["password"],
});
})};
Controler file for operations
const express = require('express');
const router = express.Router();
const Joi = require('joi');
const opers = require('../operations/ssh_test');
module.exports = router;
router.post('/operations',operations);
async function operations(req,res,next){
opers.Poperation(req.body).then((data)=>{res.send(data)}).catch((data)=>{res.send(data)})
console.log('finished') }
Welcome to the world of developing with asynchronous operations in node.js. This is a very common mistake when initially learning node.js (and a common question here on StackOverflow). An asynchronous operation completes some indeterminate time in the future and meanwhile, the rest of your code continues to run. In fact your resetPassword()
function likely returns BEFORE the stream has finished and before the resetPassword result is available.
Thus you cannot return the result from the resetPassword function directly because the function returns before the result is ready. Instead, you will have to pass in a callback and get the result when the callback is called and the caller of this function will have to use the callback rather than a directly returned result. You can implement that like this:
// FILE * ./workflow/ssh.js
var Client = require('ssh2').Client;
var conn = new Client();
// var opts = require('optimist')
// .options({
// user: {
// demand: true,
// alias: 'u'
// },
// }).boolean('allow_discovery').argv;
// Definition of reset password;
var resetPassword = function(user, host, loginUser, loginPassword, callback){
var command = 'echo -e "linuxpassword\nlinuxpassword" | passwd '+ user;
conn.on('ready', function() {
console.log('Client :: ready');
conn.exec(command, function(err, stream) {
if (err) {
callback(err);
return;
}
stream.on('close', function(code, signal) {
console.log('Stream :: close :: code: ' + code + ', signal: ' + signal);
conn.end();
callback(null, code);
}).on('data', function(data) {
console.log('STDOUT: ' + data);
}).stderr.on('data', function(data) {
console.log('STDLOG: ' + data);
});
});
}).connect({
host: host,
port: 22,
username: loginUser,
password: loginPassword
});
};
exports.resetPassword = resetPassword;
And, then you can use that like this:
var ssh = require('./workflow/ssh.js');
ssh.resetPassword('test122', '192.168.0.101', 'root' , 'password', function(err, code) {
if (!err) {
console.log(code);
}
});
P.S. From your original code, it also doesn't really help you to throw from within an async callback. The exception only goes into whatever node.js infrastructure triggered the async callback, it does not get back to your original code. That's why your code has also been changed to communicate the error via the callback.
It is a node.js convention that callbacks contain at least two arguments. The first argument is an error code which should be null
if no error and an appropriate error code or error object if there is an error. The second argument (and any other arguments you want to have) then communicate a successful result. It is useful to follow this convention since it is both consistent with how node.js does it elsewhere and it is compatible with some mechanical error handling such as done when interfaces are modified to use promises.
The return value from the on close event is only returning out of the closure. You need to provide either a callback hook or a result object as a parameter from which to retrieve the result in the signature of the resetPassword method you export from the module.