From 8eae34d3c84922f4a757b5db1d404eeca8d0194c Mon Sep 17 00:00:00 2001 From: neekey Date: Sun, 26 Mar 2017 15:22:29 +1100 Subject: [PATCH 1/6] updated to 0.1.6 --- CHANGELOG.md | 10 +++++++++- package.json | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bd95519..25687bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## [2017-03-26](https://github.com/neekey/ps/pull/35) +- publish 0.1.5 +- Add parent process ID support for windows +- use `spawn` to replace `exec` for Linux/Unix system +- add appVeyor integration +- use Travis for npm publishing +- refactor the implementation of `kill()`, now just a wrapper of built-in `process.kill()` + ## 2016-06-23 - Publish 0.1.2 - change `command` and `argument` matching to case insensitive. @@ -14,4 +22,4 @@ - Publish 0.0.5. - Merge [#5](https://github.com/neekey/ps/pull/5): Add license type MIT. -- Merge [#6](https://github.com/neekey/ps/pull/6): Allow for stdout to return the data in chunks. \ No newline at end of file +- Merge [#6](https://github.com/neekey/ps/pull/6): Allow for stdout to return the data in chunks. diff --git a/package.json b/package.json index fd54ca7..6442d9f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ps-node", - "version": "0.1.5", + "version": "0.1.6", "description": "A process lookup utility", "main": "index.js", "repository": { From 8ec87fdd06c161a451fac73ccdc6071cb99aca19 Mon Sep 17 00:00:00 2001 From: neekey Date: Sun, 26 Mar 2017 15:25:21 +1100 Subject: [PATCH 2/6] add ps options `lx` as default --- lib/index.js | 5 +++-- readme.md | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/index.js b/lib/index.js index 95e5863..a6ac5af 100644 --- a/lib/index.js +++ b/lib/index.js @@ -106,6 +106,7 @@ var Exec = module.exports = exports = function (args, callback) { * @param {String|String[]} query.pid * @param {String} query.command RegExp String * @param {String} query.arguments RegExp String + * @param {String|array} query.psargs * @param {Function} callback * @param {Object=null} callback.err * @param {Object[]} callback.processList @@ -115,9 +116,9 @@ var Exec = module.exports = exports = function (args, callback) { exports.lookup = function (query, callback) { /** - * add 'l' as default ps arguments, since the default ps output in linux like "ubuntu", wont include command arguments + * add 'lx' as default ps arguments, since the default ps output in linux like "ubuntu", wont include command arguments */ - var exeArgs = query.psargs || ['l']; + var exeArgs = query.psargs || ['lx']; var filter = {}; var idList; diff --git a/readme.md b/readme.md index acd40d4..498e2db 100644 --- a/readme.md +++ b/readme.md @@ -14,7 +14,7 @@ $ npm install ps-node This module uses different tools to get process list: -- Linux / Mac: use `ps` command. Since the default result from shell command `$ ps` will not contain "command arguments" in linux like "ubuntu", ps-node add arguments `l` as default. Which means, the default value for option `psargs` is `l`. +- Linux / Mac: use `ps` command. Since the default result from shell command `$ ps` will not contain "command arguments" in linux like "ubuntu", ps-node add arguments `lx` as default. Which means, the default value for option `psargs` is `lx`. - Win: use command `wmic process get ProcessId,CommandLine` through "cmd", more info about wmic is [here](https://social.technet.microsoft.com/Forums/windowsserver/en-US/ab6c7e6e-4ad4-4237-bab3-0349cd76c094/wmic-command-line-utilities?forum=winservercore). Anyway, there is also another tool name [tasklist](https://technet.microsoft.com/en-us/library/bb491010.aspx) in windows, which can also list all the running processes, but lack of command arguments infomation. But compared to wmic, I think this tool should have a higher performance. You should take a look at the wrapper for this tool [tasklist](https://github.com/sindresorhus/tasklist) by @sindresorhs if you are interested. ## Compatibility From 5dc26aa41b51456da4ad74a6bdf2efcc8ea436dd Mon Sep 17 00:00:00 2001 From: neekey Date: Sat, 1 Apr 2017 17:41:03 +1100 Subject: [PATCH 3/6] add timeout support for `kill()` --- lib/index.js | 34 ++++++++++------ readme.md | 7 +++- test/node_process_for_test.js | 7 +++- test/test.js | 74 +++++++++++++++++++++++++++++------ 4 files changed, 96 insertions(+), 26 deletions(-) diff --git a/lib/index.js b/lib/index.js index a6ac5af..3956a91 100644 --- a/lib/index.js +++ b/lib/index.js @@ -190,6 +190,7 @@ exports.lookup = function (query, callback) { * @param pid * @param {Object|String} signal * @param {String} signal.signal + * @param {number} signal.timeout * @param next */ @@ -200,6 +201,8 @@ exports.kill = function( pid, signal, next ){ signal = undefined; } + var checkTimeoutSeconds = (signal && signal.timeout) || 30; + if (typeof signal === 'object') { signal = signal.signal; } @@ -211,27 +214,36 @@ exports.kill = function( pid, signal, next ){ } var checkConfident = 0; + var checkTimeoutTimer = null; + var checkIsTimeout = false; function checkKilled(finishCallback) { - console.log('check kill success', pid, 'confident', checkConfident); exports.lookup({ pid: pid }, function(err, list) { - console.log('check kill success result:', (list || []).length); + if (checkIsTimeout) return; + if (err) { - finishCallback && finishCallback(err); - } else if(list.length > 0) { - checkKilled(finishCallback); + clearTimeout(checkTimeoutTimer); + finishCallback && finishCallback(err); + } else if(list.length > 0) { + checkKilled(finishCallback); + } else { + checkConfident++; + if (checkConfident === 5) { + clearTimeout(checkTimeoutTimer); + finishCallback && finishCallback(); } else { - checkConfident++; - if (checkConfident === 5) { - finishCallback && finishCallback(); - } else { - checkKilled(finishCallback); - } + checkKilled(finishCallback); } + } }); } next && checkKilled(next); + + checkTimeoutTimer = next && setTimeout(function() { + checkIsTimeout = true; + next(new Error('Kill process timeout')); + }, checkTimeoutSeconds * 1000); }; /** diff --git a/readme.md b/readme.md index 498e2db..809a58b 100644 --- a/readme.md +++ b/readme.md @@ -106,10 +106,13 @@ ps.kill( '12345', 'SIGKILL', function( err ) { }); ``` -To be compatible with prior versions, you can use object as the second parameter: +you can use object as the second parameter to pass more options: ```js -ps.kill( '12345', { signal: 'SIGKILL' }, function(){}); +ps.kill( '12345', { + signal: 'SIGKILL', + timeout: 10, // will set up a ten seconds timeout if the killing is not successful +}, function(){}); ``` diff --git a/test/node_process_for_test.js b/test/node_process_for_test.js index 667f07b..da7c0cd 100644 --- a/test/node_process_for_test.js +++ b/test/node_process_for_test.js @@ -1,7 +1,10 @@ var now = Date.now(); console.log('[child] child process start!'); +function doSomething() { + return null; +} + setInterval(function () { - var interval = Date.now() - now; - console.log('[child] Timer finished, time consuming: ' + interval); + doSomething(); }, 50); diff --git a/test/test.js b/test/test.js index 209a5bc..765b210 100644 --- a/test/test.js +++ b/test/test.js @@ -2,7 +2,6 @@ var PS = require('../index'); var CP = require('child_process'); var assert = require('assert'); var Path = require('path'); -var IS_WIN = process.platform === 'win32'; var serverPath = Path.resolve(__dirname, './node_process_for_test.js'); var UpperCaseArg = '--UPPER_CASE'; @@ -20,6 +19,16 @@ function killProcess() { } } +var processKill = process.kill; + +function mockKill() { + process.kill = function() {}; +} + +function restoreKill() { + process.kill = processKill; +} + describe('test', function () { before(function (done) { PS.lookup({arguments: 'node_process_for_test'}, function (err, list) { @@ -97,10 +106,11 @@ describe('test', function () { }); }); - for (var i = 0; i < 20; i++) { - describe('#kill() test round: ' + i, function () { + describe('#kill()', function () { - it('kill', function (done) { + it('kill', function (done) { + PS.lookup({pid: pid}, function (err, list) { + assert.equal(list.length, 1); PS.kill(pid, function (err) { assert.equal(err, null); PS.lookup({pid: pid}, function (err, list) { @@ -109,15 +119,20 @@ describe('test', function () { }); }); }); + }); - it('should not throw an exception if the callback is undefined', function (done) { - assert.doesNotThrow(function () { - PS.kill(pid); - setTimeout(done, 400); + it('should not throw an exception if the callback is undefined', function (done) { + assert.doesNotThrow(function () { + PS.kill(pid); + PS.kill(pid, function() { + done(); }); }); + }); - it('should force kill when opts.signal is SIGKILL', function (done) { + it('should force kill when opts.signal is SIGKILL', function (done) { + PS.lookup({pid: pid}, function (err, list) { + assert.equal(list.length, 1); PS.kill(pid, {signal: 'SIGKILL'}, function (err) { assert.equal(err, null); PS.lookup({pid: pid}, function (err, list) { @@ -126,8 +141,11 @@ describe('test', function () { }); }); }); + }); - it('should throw error when opts.signal is invalid', function (done) { + it('should throw error when opts.signal is invalid', function (done) { + PS.lookup({pid: pid}, function (err, list) { + assert.equal(list.length, 1); PS.kill(pid, {signal: 'INVALID'}, function (err) { assert.notEqual(err, null); PS.kill(pid, function(){ @@ -136,5 +154,39 @@ describe('test', function () { }); }); }); - } + }); + + describe('#kill() timeout: ', function () { + it('it should timeout after 30secs by default if the killing is not successful', function(done) { + mockKill(); + var killStartDate = Date.now(); + PS.lookup({pid: pid}, function (err, list) { + assert.equal(list.length, 1); + PS.kill(pid, function (err) { + assert.equal(Date.now() - killStartDate >= 30 * 1000, true); + assert.equal(err.message.indexOf('timeout') >= 0, true); + restoreKill(); + PS.kill(pid, function(){ + done(); + }); + }); + }); + }); + + it('it should be able to set option to set the timeout', function(done) { + mockKill(); + var killStartDate = Date.now(); + PS.lookup({pid: pid}, function (err, list) { + assert.equal(list.length, 1); + PS.kill(pid, { timeout: 5 }, function (err) { + assert.equal(Date.now() - killStartDate >= 5 * 1000, true); + assert.equal(err.message.indexOf('timeout') >= 0, true); + restoreKill(); + PS.kill(pid, function(){ + done(); + }); + }); + }); + }); + }); }); From d6efd819878e5a1ded8f1a54466766d532df1af6 Mon Sep 17 00:00:00 2001 From: neekey Date: Fri, 21 Apr 2017 14:57:05 +1000 Subject: [PATCH 4/6] optimize checkConfident --- lib/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/index.js b/lib/index.js index 3956a91..893c57b 100644 --- a/lib/index.js +++ b/lib/index.js @@ -225,6 +225,7 @@ exports.kill = function( pid, signal, next ){ clearTimeout(checkTimeoutTimer); finishCallback && finishCallback(err); } else if(list.length > 0) { + checkConfident = (checkConfident - 1) || 0; checkKilled(finishCallback); } else { checkConfident++; From 26d1902984bc1ebcf2c05b02ff21f919b333da3f Mon Sep 17 00:00:00 2001 From: neekey Date: Fri, 21 Apr 2017 15:06:39 +1000 Subject: [PATCH 5/6] use Sinon fakeTimer to optimize the test for timeout --- package.json | 1 + test/test.js | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/package.json b/package.json index 6442d9f..d0ec26a 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ }, "license": "MIT", "devDependencies": { + "sinon": "^2.1.0", "mocha": "^2.4.5" } } diff --git a/test/test.js b/test/test.js index 765b210..a682004 100644 --- a/test/test.js +++ b/test/test.js @@ -2,6 +2,7 @@ var PS = require('../index'); var CP = require('child_process'); var assert = require('assert'); var Path = require('path'); +var Sinon = require('sinon'); var serverPath = Path.resolve(__dirname, './node_process_for_test.js'); var UpperCaseArg = '--UPPER_CASE'; @@ -159,6 +160,7 @@ describe('test', function () { describe('#kill() timeout: ', function () { it('it should timeout after 30secs by default if the killing is not successful', function(done) { mockKill(); + var clock = Sinon.useFakeTimers(); var killStartDate = Date.now(); PS.lookup({pid: pid}, function (err, list) { assert.equal(list.length, 1); @@ -167,14 +169,17 @@ describe('test', function () { assert.equal(err.message.indexOf('timeout') >= 0, true); restoreKill(); PS.kill(pid, function(){ + clock.restore(); done(); }); }); + clock.tick(30 * 1000); }); }); it('it should be able to set option to set the timeout', function(done) { mockKill(); + var clock = Sinon.useFakeTimers(); var killStartDate = Date.now(); PS.lookup({pid: pid}, function (err, list) { assert.equal(list.length, 1); @@ -183,9 +188,11 @@ describe('test', function () { assert.equal(err.message.indexOf('timeout') >= 0, true); restoreKill(); PS.kill(pid, function(){ + clock.restore(); done(); }); }); + clock.tick(5 * 1000); }); }); }); From 6c829ed8e1cd8eb3857faf45ebf7f1790bac6bc0 Mon Sep 17 00:00:00 2001 From: neekey Date: Fri, 21 Apr 2017 15:31:28 +1000 Subject: [PATCH 6/6] add CHANGELOG for 0.1.6 --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 25687bc..26c3d2c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [2017-04-21](https://github.com/neekey/ps/pull/48) +- publish 0.1.6 +- use `lx` as default options for `ps` command +- remove debugging console log for `kill()` +- add timeout for `kill()`, default to 30s + ## [2017-03-26](https://github.com/neekey/ps/pull/35) - publish 0.1.5 - Add parent process ID support for windows