TreeKill.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. 'use strict';
  2. // From https://raw.githubusercontent.com/pkrumins/node-tree-kill/master/index.js
  3. var childProcess = require('child_process');
  4. var spawn = childProcess.spawn;
  5. var exec = childProcess.exec;
  6. module.exports = function (pid, signal, callback) {
  7. var tree = {};
  8. var pidsToProcess = {};
  9. tree[pid] = [];
  10. pidsToProcess[pid] = 1;
  11. switch (process.platform) {
  12. case 'win32':
  13. exec('taskkill /pid ' + pid + ' /T /F', { windowsHide: true }, callback);
  14. break;
  15. case 'darwin':
  16. buildProcessTree(pid, tree, pidsToProcess, function (parentPid) {
  17. return spawn('pgrep', ['-P', parentPid]);
  18. }, function () {
  19. killAll(tree, signal, callback);
  20. });
  21. break;
  22. // case 'sunos':
  23. // buildProcessTreeSunOS(pid, tree, pidsToProcess, function () {
  24. // killAll(tree, signal, callback);
  25. // });
  26. // break;
  27. default: // Linux
  28. buildProcessTree(pid, tree, pidsToProcess, function (parentPid) {
  29. return spawn('ps', ['-o', 'pid', '--no-headers', '--ppid', parentPid]);
  30. }, function () {
  31. killAll(tree, signal, callback);
  32. });
  33. break;
  34. }
  35. };
  36. function killAll (tree, signal, callback) {
  37. var killed = {};
  38. try {
  39. Object.keys(tree).forEach(function (pid) {
  40. tree[pid].forEach(function (pidpid) {
  41. if (!killed[pidpid]) {
  42. killPid(pidpid, signal);
  43. killed[pidpid] = 1;
  44. }
  45. });
  46. if (!killed[pid]) {
  47. killPid(pid, signal);
  48. killed[pid] = 1;
  49. }
  50. });
  51. } catch (err) {
  52. if (callback) {
  53. return callback(err);
  54. } else {
  55. console.error(err);
  56. }
  57. }
  58. if (callback) {
  59. return callback();
  60. }
  61. }
  62. function killPid(pid, signal) {
  63. try {
  64. process.kill(parseInt(pid, 10), signal);
  65. }
  66. catch (err) {
  67. if (err.code !== 'ESRCH')
  68. console.error(err);
  69. }
  70. }
  71. function buildProcessTree (parentPid, tree, pidsToProcess, spawnChildProcessesList, cb) {
  72. var ps = spawnChildProcessesList(parentPid);
  73. var allData = '';
  74. ps.on('error', function(err) {
  75. console.error(err);
  76. });
  77. if (ps.stdout) {
  78. ps.stdout.on('data', function (data) {
  79. data = data.toString('ascii');
  80. allData += data;
  81. });
  82. }
  83. var onClose = function (code) {
  84. delete pidsToProcess[parentPid];
  85. if (code !== 0) {
  86. // no more parent processes
  87. if (Object.keys(pidsToProcess).length == 0) {
  88. cb();
  89. }
  90. return;
  91. }
  92. var pids = allData.match(/\d+/g) || [];
  93. if (pids.length === 0)
  94. return cb();
  95. pids.forEach(function (pid) {
  96. pid = parseInt(pid, 10);
  97. tree[parentPid].push(pid);
  98. tree[pid] = [];
  99. pidsToProcess[pid] = 1;
  100. buildProcessTree(pid, tree, pidsToProcess, spawnChildProcessesList, cb);
  101. });
  102. };
  103. ps.on('close', onClose);
  104. }