Node.js 节点生成多个shell进程问题
我开发了一个模块,使用Node.js 节点生成多个shell进程问题,node.js,shell,process,promise,spawn,Node.js,Shell,Process,Promise,Spawn,我开发了一个模块,使用child\u进程spawn执行通用命令。 我在这个模块中有两个api,一个是单命令执行api,CommandLine.execute,另一个是多命令执行api,CommandLine.executeCommands,我以这种方式调用它们: // commandItemsArray is a list of commands list // that is an array of [command, options, arguments] commandItemsArr
child\u进程spawn
执行通用命令。
我在这个模块中有两个api,一个是单命令执行api,CommandLine.execute
,另一个是多命令执行api,CommandLine.executeCommands
,我以这种方式调用它们:
// 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 );
});
或
此模块是独立的(仅依赖于节点内置模块),代码如下:
(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);
我正在使用承诺。all
生成多个进程,等待执行,并在节点缓冲区中收集stdout
输出,如:
// Listen for stdout data
child.stdout.on('data', function(_data) {
console.log( ( new Buffer(_data)).toString() );
data = Buffer.concat([data, _data]);
});
在退出子事件中,我返回子进程退出代码和结构中的数据:
child.on('exit', function(exitCode) {
return resolve( { data : data.toString('utf-8'), code : exitCode } );
});
虽然执行某些命令没有问题,但执行诸如ls
之类的shell命令会返回意外的结果,例如我没有在PromiseAll
方法的回调中获得预期的结果,我不理解为什么
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);
});
一个疑问是关于节点缓冲区级联的解释,这似乎很棘手:
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')}
将整个缓冲区链接为字符串,但我想知道utf-8
是否是stdout
输出的正确编码,当然,假设我们正在讨论shell命令
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]);
});