mirror of
https://github.com/nuintun/command-manager.git
synced 2025-06-07 03:14:07 +08:00
update files
This commit is contained in:
parent
47a857cd5b
commit
bf76db01b9
@ -4,7 +4,8 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var spawn = require('child_process').spawn;
|
var spawn = require('./spawn');
|
||||||
|
var threadKill = require('./thread-kill');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Emulator
|
* Emulator
|
||||||
@ -17,7 +18,7 @@ function Emulator(task){
|
|||||||
|
|
||||||
Emulator.prototype = {
|
Emulator.prototype = {
|
||||||
start: function (){
|
start: function (){
|
||||||
this.thread = this.exec(this.task.command, {
|
this.thread = spawn(this.task.command, {
|
||||||
env: this.task.env,
|
env: this.task.env,
|
||||||
cwd: this.task.cwd
|
cwd: this.task.cwd
|
||||||
});
|
});
|
||||||
@ -26,53 +27,17 @@ Emulator.prototype = {
|
|||||||
},
|
},
|
||||||
stop: function (){
|
stop: function (){
|
||||||
if (this.thread) {
|
if (this.thread) {
|
||||||
this.exec('taskkill /t /f /pid ' + this.thread.pid);
|
var context = this;
|
||||||
|
|
||||||
['stdin', 'stdout', 'stderr'].forEach(function (stream){
|
threadKill(this.thread.pid, function (){
|
||||||
this.thread[stream].removeAllListeners();
|
['stdin', 'stdout', 'stderr'].forEach(function (stream){
|
||||||
}, this);
|
context.thread[stream].removeAllListeners();
|
||||||
|
});
|
||||||
|
|
||||||
this.thread = null;
|
context.thread = null;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
|
||||||
exec: function (){
|
|
||||||
var parsed = normalizeExecArgs.apply(null, arguments);
|
|
||||||
|
|
||||||
return spawn(parsed.shell, parsed.args, parsed.options);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* normalize exec args
|
|
||||||
* @param command
|
|
||||||
* @param options
|
|
||||||
* @returns {{cmd: *, shell: *, args: *, options: *}}
|
|
||||||
*/
|
|
||||||
function normalizeExecArgs(command, options){
|
|
||||||
var shell, args;
|
|
||||||
|
|
||||||
// Make a shallow copy before patching so we don't clobber the user's
|
|
||||||
// options object.
|
|
||||||
options = options || {};
|
|
||||||
|
|
||||||
if (process.platform === 'win32') {
|
|
||||||
shell = process.env.comspec || 'cmd.exe';
|
|
||||||
args = ['/s', '/c', '"' + command + '"'];
|
|
||||||
options.windowsVerbatimArguments = true;
|
|
||||||
} else {
|
|
||||||
shell = '/bin/sh';
|
|
||||||
args = ['-c', command];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.shell) {
|
|
||||||
shell = options.shell;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
shell: shell,
|
|
||||||
args: args,
|
|
||||||
options: options
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = Emulator;
|
module.exports = Emulator;
|
||||||
|
49
bin/spawn.js
Normal file
49
bin/spawn.js
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/**
|
||||||
|
* Created by nuintun on 2016/1/14.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var spawn = require('child_process').spawn;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* normalize exec args
|
||||||
|
* @param command
|
||||||
|
* @param options
|
||||||
|
* @returns {{cmd: *, shell: *, args: *, options: *}}
|
||||||
|
*/
|
||||||
|
function normalizeExecArgs(command, options){
|
||||||
|
var shell, args;
|
||||||
|
|
||||||
|
// Make a shallow copy before patching so we don't clobber the user's
|
||||||
|
// options object.
|
||||||
|
options = options || {};
|
||||||
|
|
||||||
|
if (process.platform === 'win32') {
|
||||||
|
shell = process.env.comspec || 'cmd.exe';
|
||||||
|
args = ['/s', '/c', '"' + command + '"'];
|
||||||
|
options.windowsVerbatimArguments = true;
|
||||||
|
} else {
|
||||||
|
shell = '/bin/sh';
|
||||||
|
args = ['-c', command];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.shell) {
|
||||||
|
shell = options.shell;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
shell: shell,
|
||||||
|
args: args,
|
||||||
|
options: options
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* exec thread
|
||||||
|
*/
|
||||||
|
module.exports = function (){
|
||||||
|
var parsed = normalizeExecArgs.apply(null, arguments);
|
||||||
|
|
||||||
|
return spawn(parsed.shell, parsed.args, parsed.options);
|
||||||
|
};
|
116
bin/thread-kill.js
Normal file
116
bin/thread-kill.js
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
/**
|
||||||
|
* Created by nuintun on 2016/1/14.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var spawn = require('./spawn');
|
||||||
|
var exec = require('child_process').exec;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param pid
|
||||||
|
* @param signal
|
||||||
|
* @param callback
|
||||||
|
*/
|
||||||
|
module.exports = function (pid, signal, callback){
|
||||||
|
var tree = {};
|
||||||
|
var pidsToProcess = {};
|
||||||
|
|
||||||
|
tree[pid] = [];
|
||||||
|
pidsToProcess[pid] = 1;
|
||||||
|
|
||||||
|
if (typeof signal === 'function') {
|
||||||
|
signal = 'SIGKILL';
|
||||||
|
callback = signal;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (process.platform) {
|
||||||
|
// win32
|
||||||
|
case 'win32':
|
||||||
|
exec('taskkill /pid ' + pid + ' /T /F', callback);
|
||||||
|
break;
|
||||||
|
// darwin
|
||||||
|
case 'darwin':
|
||||||
|
buildProcessTree(pid, tree, pidsToProcess, function (parentPid){
|
||||||
|
return spawn('pgrep', ['-P', parentPid]);
|
||||||
|
}, function (){
|
||||||
|
killAll(tree, signal, callback);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
// linux
|
||||||
|
default:
|
||||||
|
buildProcessTree(pid, tree, pidsToProcess, function (parentPid){
|
||||||
|
return spawn('ps', ['-o', 'pid', '--no-headers', '--ppid', parentPid]);
|
||||||
|
}, function (){
|
||||||
|
killAll(tree, signal, callback);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function killAll(tree, signal, callback){
|
||||||
|
var killed = {};
|
||||||
|
|
||||||
|
try {
|
||||||
|
Object.keys(tree).forEach(function (pid){
|
||||||
|
tree[pid].forEach(function (pidpid){
|
||||||
|
if (!killed[pidpid]) {
|
||||||
|
killPid(pidpid, signal);
|
||||||
|
killed[pidpid] = 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (!killed[pid]) {
|
||||||
|
killPid(pid, signal);
|
||||||
|
killed[pid] = 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
if (callback) {
|
||||||
|
return callback(error);
|
||||||
|
} else {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (callback) {
|
||||||
|
return callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function killPid(pid, signal){
|
||||||
|
try {
|
||||||
|
process.kill(parseInt(pid, 10), signal);
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
if (error.code !== 'ESRCH') throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildProcessTree(parentPid, tree, pidsToProcess, spawnChildProcessesList, callback){
|
||||||
|
var allData = '';
|
||||||
|
var ps = spawnChildProcessesList(parentPid);
|
||||||
|
|
||||||
|
ps.stdout.on('data', function (data){
|
||||||
|
allData += data.toString('ascii');
|
||||||
|
});
|
||||||
|
|
||||||
|
var onClose = function (code){
|
||||||
|
delete pidsToProcess[parentPid];
|
||||||
|
|
||||||
|
if (code != 0) {
|
||||||
|
// no more parent processes
|
||||||
|
if (Object.keys(pidsToProcess).length == 0) {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
allData.match(/\d+/g).forEach(function (pid){
|
||||||
|
pid = parseInt(pid, 10);
|
||||||
|
tree[parentPid].push(pid);
|
||||||
|
tree[pid] = [];
|
||||||
|
pidsToProcess[pid] = 1;
|
||||||
|
buildProcessTree(pid, tree, pidsToProcess, spawnChildProcessesList, callback);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
ps.on('close', onClose);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user