Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
875 views
in Technique[技术] by (71.8m points)

node.js - How to capture the 'code' value into a variable?

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;
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){

var command = 'echo -e "linuxpassword
linuxpassword" | passwd '+ user;

conn.on('ready', function() {
  console.log('Client :: ready');
  conn.exec(command, function(err, stream) {
    if (err) throw err;
    stream.on('close', function(code, signal) {
      console.log('Stream :: close :: code: ' + code + ', signal: ' + signal);
      conn.end();
      return(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;

I'm calling the resetPassword password function from an other module , say test.js as below.

var ssh = require('./workflow/ssh.js');

result = ssh.resetPassword('test122', '192.168.0.101', 'root' , 'password');
console.log(result)

But the console.log says "undefined". Tried using the process.nextTick, but no luck. Please help.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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
linuxpassword" | 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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...