nyx_server
Version:
Node内容发布
115 lines (97 loc) • 3.65 kB
JavaScript
/* global process */
var cp = require('child_process');
var path = require('path');
var Promise = require('bluebird');
var _ = require('lodash');
var which = require('which');
var log4js = require("log4js");
var log = log4js.getLogger("cmd");
//var PThrottler = require('p-throttler'); 暂时先不使用
var createError = require('./createError');
// The concurrency limit here is kind of magic. You don't really gain a lot from
// having a large number of commands spawned at once, so it isn't super
// important for this number to be large. However, it would still be nice to
// *know* how high this number can be, rather than having to guess low.
//var throttler = new PThrottler(50);
var winBatchExtensions;
var winWhichCache;
var isWin = process.platform === 'win32';
if (isWin) {
winBatchExtensions = ['.bat', '.cmd'];
winWhichCache = {};
}
function getWindowsCommand(command) {
var fullCommand;
var extension;
// Do we got the value converted in the cache?
if (_.has(winWhichCache, command)) {
return winWhichCache[command];
}
// Use which to retrieve the full command, which puts the extension in the end
try {
fullCommand = which.sync(command);
} catch (err) {
return winWhichCache[command] = command;
}
extension = path.extname(fullCommand).toLowerCase();
// Does it need to be converted?
if (winBatchExtensions.indexOf(extension) === -1) {
return winWhichCache[command] = command;
}
return winWhichCache[command] = fullCommand;
}
// Executes a shell command, buffering the stdout and stderr
// If an error occurs, a meaningful error is generated
// Returns a promise that gets fulfilled if the command succeeds
// or rejected if it fails
function executeCmd(command, args, options) {
log.debug("命令行参数 : "+JSON.stringify(arguments))
var process;
var stderr = '';
var stdout = '';
return new Promise(function(resolve , reject){
// Windows workaround for .bat and .cmd files, see #626
if (isWin) {
command = getWindowsCommand(command);
}
// Buffer output, reporting progress
process = cp.spawn(command, args, options);
process.stdout.on('data', function (data) {
data = data.toString();
stdout += data;
});
process.stderr.on('data', function (data) {
data = data.toString();
stderr += data;
});
// If there is an error spawning the command, reject the promise
process.on('error', reject);
// Listen to the close event instead of exit
// They are similar but close ensures that streams are flushed
process.on('close', function (code) {
var fullCommand;
var error;
if (code) {
// Generate the full command to be presented in the error message
if (!Array.isArray(args)) {
args = [];
}
fullCommand = command;
fullCommand += args.length ? ' ' + args.join(' ') : '';
// Build the error instance
error = createError('Failed to execute "' + fullCommand + '", exit code of #' + code, 'ECMDERR', {
stdout : stdout,
details: stderr,
exitCode: code
});
reject(error);
return;
}
resolve([stdout, stderr]);
});
});
}
function cmd(command, args, options) {
return executeCmd(command, args, options);
}
module.exports = cmd;