tutorial español comandos cluster node.js shell process promise spawn

node.js - español - El nodo genera múltiples problemas en el proceso de shell



comandos cluster linux (0)

Desarrollé un módulo para ejecutar un comando genérico utilizando child_process spawn . Tengo dos api en este módulo: una sola ejecución de comandos api, CommandLine.execute y una ejecución de comandos múltiples api, CommandLine.executeCommands , que llamo de esta manera:

// commandItemsArray is a list of commands list // that is an array of [command, options, arguments] commandItemsArray = [ [''ls'',''-l'',''./''], [''ls'',''-a'',''./''] ]; command.executeCommands( commandItemsArray , function(results) { console.log( results ); } , function(error) { console.log( error ); });

o

commandItemsArray = [ [''ls'',''-l'',''./''] ]; command.executeCommands( commandItemsArray , function(results) { console.log( results ); } , function(error) { console.log( error ); });

Este módulo es independiente (depende solo de los módulos incorporados en el nodo) y ese es el código:

(function() { var CommandLine; CommandLine = (function() { var cp = require(''child_process''); /** * Command line helper module * This module is standalone * @author: loretoparisi at gmail dot com */ function CommandLine(options,logger) { var self=this; // defaults this._options = { // true to debug debug : false, // true to show errors error : true }; // override defaults for (var attrname in options) { this._options[attrname] = options[attrname]; } /** * Wrappar around Promise.all */ this.PromiseAll = function(items, block, done, fail) { var self = this; var promises = [], index = 0; items.forEach(function(item) { promises.push(function(item, i) { return new Promise(function(resolve, reject) { if (block) { block.apply(this, [item, index, resolve, reject]); } }); }(item, ++index)) }); Promise.all(promises).then(function AcceptHandler(results) { if (done) done(results); }, function ErrorHandler(error) { if (fail) fail(error); }); }; //PromiseAll } /** * Execute a command * @param commands Array of command, options, arguments * @example [''ls'',''-l'',''./''] * @param resolve Block success block * @param reject Block rejection block */ CommandLine.prototype.execute = function(command, resolve, reject) { var self=this; resolve = resolve || function(results) {}; reject = reject || function(error) {}; return self.ExecutionBlock(item, index, resolve, reject); } //execute /** * Execute a list of commands * @param commands Array of command array of of command, options, arguments * @example [ [''ls'',''-l'',''./''], [''ls'', ''-a'', ''./''] ] * @param resolve Block success block * @param reject Block rejection block */ CommandLine.prototype.executeCommands = function(commands, resolve, reject) { var self=this; resolve = resolve || function(results) {}; reject = reject || function(error) {}; /** * Execution block handler */ var ExecutionBlock = function(item, index, resolve, reject) { var executable = item[0]; // first elem is command var options = item.splice(1,item.length); if(self._options.debug) { console.log( item ); console.log( executable, options.join('' '') ); } var data = new Buffer("",''utf-8''); // LP: now spawn the power! var child = cp.spawn(executable, options); // Listen for an exit event: child.on(''exit'', function(exitCode) { return resolve( { data : data.toString(''utf-8''), code : exitCode } ); }); // Listen for stdout data child.stdout.on(''data'', function(_data) { console.log( ( new Buffer(_data)).toString() ); data = Buffer.concat([data, _data]); }); // child error child.stderr.on(''data'', function(data) { if(self._options.error) { console.log(''err data: '' + data); } // on error, kill this child child.kill(); return reject(new Error(data.toString())); } ); } //ExecutionBlock self.PromiseAll(commands , function(item, index, _resolve, _reject) { ExecutionBlock(item, index, _resolve, _reject); } , function(results) { // aggregated results // all execution done here. The process exitCodes will be returned // array index is the index of the processed that exited return resolve(results); } , function(error) { // error return reject(error); }); } //executeCommands return CommandLine; })(); module.exports = CommandLine; }).call(this);

Estoy usando Promise.all para generar múltiples procesos, esperar la ejecución y recopilar salida stdout en un Buffer nodo como:

// Listen for stdout data child.stdout.on(''data'', function(_data) { console.log( ( new Buffer(_data)).toString() ); data = Buffer.concat([data, _data]); });

En el evento hijo de exit muy, devuelvo el código de salida y los datos del proceso secundario en una estructura:

child.on(''exit'', function(exitCode) { return resolve( { data : data.toString(''utf-8''), code : exitCode } ); });

Si bien, la ejecución de algunos comandos no tiene ningún problema, la ejecución de comandos del shell como ls me devuelve resultados inesperados, como que no obtengo los resultados esperados en la devolución de llamada del método PromiseAll , y no entiendo por qué.

self.PromiseAll(commands , function(item, index, _resolve, _reject) { ExecutionBlock(item, index, _resolve, _reject); } , function(results) { // aggregated results // all execution done here. The process exitCodes will be returned // array index is the index of the processed that exited return resolve(results); } , function(error) { // error return reject(error); });

Una duda es acerca de la concatenación de Buffer nodo explicada aquí , que parece ser difícil:

var data = new Buffer("",''utf-8''); // LP: now spawn the power! var child = cp.spawn(executable, options); // Listen for an exit event: child.on(''exit'', function(exitCode) { return resolve( { data : data.toString(''utf-8''), code : exitCode } ); }); // Listen for stdout data child.stdout.on(''data'', function(_data) { console.log( ( new Buffer(_data)).toString() ); data = Buffer.concat([data, _data]); });

{ data : data.toString(''utf-8'')} mantener el buffer entero encadenado como cadena, pero me pregunto si el utf-8 es la codificación correcta para la salida stdout , se supone que estamos hablando de comandos de shell por supuesto.