3

I am using ssh2 nodejs module to connect to a UNIX application and run a script and it is successful. Now i want to connect to multiple servers one by one and get the output and store it. When i try using a for loop to pass the servers one by one from a json as input to the ssh2 the for loop completes much faster than the block which is supposed to get the output from the server. This is also causing me handshake error. Kindly help

Here is the code

inc_cron.schedule("*/20 * * * * *", function(id) {    
        });

//inc_cron.js

var cronFunction = function(inputStr) { 
                  if(appNames['applications'].length>0){ 
                                for (i = 0; i < appNames["applications"].length; i++) {  
                                  getDataFromServer(appNames["applications"][i].Name,appNames["applications"][i].hostname, appNames["applications"][i].username, appNames["applications"][i].password, appNames["applications"][i].log_path, function(err, data) { 
                                                if(err) {
                                                  logger.info("Error is in cronFunction = ", err);
                                                } else if(data) { 
                                                                output_data +=data;   
                                                }  ssh.close_second();
                                  }); 
                                } 
                }  
}

var getDataFromServer = function(Name,hostname, username, password, log_path, cb) { 
  ssh.close_second();
  ssh.connect_second({
    host: hostname,
    username: username,
    password: password
  }, function(err) {
    if(err) {
      logger.error('Err: ', err);
    } else {  
                                ssh.sftp("",'grep -o "ERROR" '+log_path+'.log.'+yr+'-'+mnth+'-* | wc -l', function(err, data) {
                                                      cb(err, data); 
                                });     }   });  }


//connect.js

SSHConnection.prototype.sftp = function(type, path,  cb) {
  var self = this;
  var log_data = '';
  self.connection2.exec(path +' ' + type,  { pty: true }, function(err, stream) {
                if (err) {
      logger.log('SECOND :: exec error: ' + err); 
    }
                stream.on('end', function() {
      self.connection2.end(); // close parent (and this) connection
    }).on('data', function(data) {
      logger.info(data.toString());
    });
                  }); 
};
Sshastry
  • 57
  • 1
  • 8

2 Answers2

0

Without watch your code, be sure to handle correctly the async issue with ssh2... use a promise factory.

Mech45
  • 321
  • 1
  • 9
  • The package [node-ssh](https://www.npmjs.com/package/node-ssh) is probably the best approach to use this lib with promises. – austin_ce Sep 12 '18 at 15:36
0

One way to do this is to use es7 async await. For this you have to rewrite your getDataFromServer function to return a promise:

var getDataFromServer = function(Name,hostname, username, password, log_path, cb) { 
    return new Promise(function(resolve,reject){
        ssh.close_second();
        sh.connect_second({
            host: hostname,
            username: username,
            password: password
        },function(err) {
            if(err){
                reject(err)
            }else{
                ssh.sftp("",'grep -o "ERROR" '+log_path+'.log.'+yr+'-'+mnth+'-* | wc -l', function(err, data) {
                    if(err){
                        reject(err)
                    }else{ 
                        resolve(data)
                    }
                })
            }
        })
    })
}

now you can rewrite your cron function to be an async function.

var cronFunction = async function(inputStr) { 
    if(appNames['applications'].length>0){ 
        for (i = 0; i < appNames["applications"].length; i++) {
            try{
                output_data + = await getDataFromServer(appNames["applications"][i].Name,appNames["applications"][i].hostname, appNames["applications"][i].username, appNames["applications"][i].password, appNames["applications"][i].log_path)
            }catch(err){
               logger.info("Error is in cronFunction = ", err);
            }
            ssh.close_second();
        }
    } 
}

async await enables you to write async code in syncronous coding style. However async await is currently (node 7.*) hidden behind a flag (--harmony-async-await). this feature will be enable by default in the upcomming node release (8.0.0) in April 2017.

so to start your app you currently have to use

node --harmony-async-await yourapp.js

P.S.: This code is currently untested and most probably contains bugs .. but you get the idea.

austin_ce
  • 1,063
  • 15
  • 28
Holger Will
  • 7,228
  • 1
  • 31
  • 39
  • Thanks ...will try it...... :) Also i forgot to mention one more error im facing....the for loop works for some 20 times.....and once the count hits 20 ....i get a HandShanke error ....... Any suggestions on that ??? – Sshastry Jan 13 '17 at 09:00
  • that should be gone with `async await` as well, as there will always be just one open connection. – Holger Will Jan 13 '17 at 09:14