pidtree
Advanced tools
Comparing version 0.2.0 to 0.3.0
@@ -6,17 +6,110 @@ #!/usr/bin/env node | ||
var os = require('os'); | ||
var pidtree = require('..'); | ||
// | ||
// Change the default parent PID if running | ||
// under Windows. | ||
// | ||
let ppid = 1; | ||
if (process.platform === 'win32') { | ||
ppid = 0; | ||
function help() { | ||
var help = ` Usage | ||
$ pidtree <ppid> | ||
Options | ||
--list To print the pids as a list. | ||
Examples | ||
$ pidtree | ||
$ pidtree --list | ||
$ pidtree 1 | ||
$ pidtree 1 --list | ||
`; | ||
console.log(help); | ||
} | ||
require('..')(process.argv[2] || ppid, (err, data) => { | ||
if (err) { | ||
return console.error(err); | ||
function list(ppid) { | ||
pidtree(ppid === undefined ? -1 : ppid, function(err, list) { | ||
if (err) { | ||
console.error(err.message); | ||
return; | ||
} | ||
console.log(list.join(os.EOL)); | ||
}); | ||
} | ||
function tree(ppid) { | ||
pidtree(ppid, {advanced: true}, function(err, list) { | ||
if (err) { | ||
console.error(err.message); | ||
return; | ||
} | ||
var parents = {}; // Hash Map of parents | ||
var tree = {}; // Adiacency Hash Map | ||
while (list.length > 0) { | ||
var e = list.pop(); | ||
if (tree[e.ppid]) { | ||
tree[e.ppid].push(e.pid); | ||
} else { | ||
tree[e.ppid] = [e.pid]; | ||
} | ||
if (ppid === -1) { | ||
parents[e.pid] = e.ppid; | ||
} | ||
} | ||
var roots = [ppid]; | ||
if (ppid === -1) { | ||
// Get all the roots | ||
roots = Object.keys(tree).filter(node => parents[node] === undefined); | ||
} | ||
roots.forEach(root => print(tree, root)); | ||
}); | ||
function print(tree, start) { | ||
function printBranch(node, branch) { | ||
const isGraphHead = branch.length === 0; | ||
const children = tree[node] || []; | ||
let branchHead = ''; | ||
if (!isGraphHead) { | ||
branchHead = children.length > 0 ? '┬ ' : '─ '; | ||
} | ||
console.log(`${branch}${branchHead}${node}`); | ||
var baseBranch = branch; | ||
if (!isGraphHead) { | ||
const isChildOfLastBranch = branch.slice(-2) === '└─'; | ||
baseBranch = branch.slice(0, -2) + (isChildOfLastBranch ? ' ' : '| '); | ||
} | ||
const nextBranch = baseBranch + '├─'; | ||
const lastBranch = baseBranch + '└─'; | ||
children.forEach((child, index) => { | ||
printBranch( | ||
child, | ||
children.length - 1 === index ? lastBranch : nextBranch | ||
); | ||
}); | ||
} | ||
printBranch(start, ''); | ||
} | ||
console.log(data.join(os.EOL)); | ||
}); | ||
} | ||
function run() { | ||
var flag; | ||
var ppid; | ||
for (var i = 2; i < process.argv.length; i++) { | ||
if (process.argv[i].startsWith('--')) { | ||
flag = process.argv[i]; | ||
} else { | ||
ppid = process.argv[i]; | ||
} | ||
} | ||
if (ppid === undefined) { | ||
ppid = -1; | ||
} | ||
if (flag === '--list') list(ppid); | ||
else if (flag === undefined) tree(ppid); | ||
else help(); | ||
} | ||
run(); |
20
index.js
@@ -12,15 +12,17 @@ 'use strict'; | ||
var tree = require('./lib/tree'); | ||
var pidtree = require('./lib/pidtree'); | ||
/** | ||
* Get the list of child pids of the given pid. | ||
* Get the list of children pids of the given pid. | ||
* @public | ||
* @param {Number|String} pid A pid. | ||
* @param {Number|String} PID A PID. If -1 will return all the pids. | ||
* @param {Object} [options] Optional options object. | ||
* @param {Boolean} [options.root=false] Include the provided pid in the list. | ||
* @param {Boolean} [options.root=false] Include the provided PID in the list. | ||
* @param {Boolean} [options.advanced=false] Returns a list of objects in the | ||
* format {pid: X, ppid: Y}. | ||
* @param {Function} [callback=undefined] Called when the list is ready. If not | ||
* provided a promise is returned instead. | ||
* @returns {Promise.<Object>} Only when the callback is not provided. | ||
* @returns {Promise.<Object[]>} Only when the callback is not provided. | ||
*/ | ||
function pidtree(pid, options, callback) { | ||
function list(pid, options, callback) { | ||
if (typeof options === 'function') { | ||
@@ -31,8 +33,8 @@ callback = options; | ||
if (typeof callback === 'function') { | ||
tree(pid, options, callback); | ||
pidtree(pid, options, callback); | ||
return; | ||
} | ||
return pify(tree, pid, options); | ||
return pify(pidtree, pid, options); | ||
} | ||
module.exports = pidtree; | ||
module.exports = list; |
@@ -7,75 +7,38 @@ 'use strict'; | ||
/** | ||
* Get the list of child pids of the given pid through the ps command. | ||
* @param {Number} pid | ||
* @param {Function} done(err, tree) | ||
* Gets the list of all the pids of the system through the ps command. | ||
* @param {Function} callback(err, list) | ||
*/ | ||
function ps(pid, done) { | ||
var args = ['-A', '-o', 'pid,ppid']; | ||
function ps(callback) { | ||
var args = ['-A', '-o', 'ppid,pid']; | ||
bin('ps', args, function(err, stdout, code) { | ||
if (err) return done(err); | ||
if (err) return callback(err); | ||
if (code !== 0) { | ||
return done(new Error('pidtree ps command exited with code ' + code)); | ||
return callback(new Error('pidtree ps command exited with code ' + code)); | ||
} | ||
// Example of stdout on *nix. | ||
// | ||
// PID PPID | ||
// 430 1 | ||
// 432 430 | ||
// 727 1 | ||
// 7166 1 | ||
// Example of stdout on Darwin | ||
// Example of stdout | ||
// | ||
// PID PPID | ||
// 430 1 | ||
// 432 430 | ||
// 727 1 | ||
// 7166 1 | ||
// PPID PID | ||
// 1 430 | ||
// 430 432 | ||
// 1 727 | ||
// 1 7166 | ||
stdout = stdout.split(os.EOL); | ||
try { | ||
stdout = stdout.split(os.EOL); | ||
var found = false; | ||
var tree = {}; | ||
for (var i = 1; i < stdout.length; i++) { | ||
var line = stdout[i].trim().split(/\s+/); | ||
if (!line || line.length !== 2) { | ||
continue; | ||
var list = []; | ||
for (var i = 1; i < stdout.length; i++) { | ||
stdout[i] = stdout[i].trim(); | ||
if (!stdout[i]) continue; | ||
stdout[i] = stdout[i].split(/\s+/); | ||
stdout[i][0] = parseInt(stdout[i][0], 10); // PPID | ||
stdout[i][1] = parseInt(stdout[i][1], 10); // PID | ||
list.push(stdout[i]); | ||
} | ||
var PID = parseInt(line[0], 10); | ||
var PPID = parseInt(line[1], 10); | ||
if (pid === PID || pid === PPID) { | ||
found = true; | ||
} | ||
// Build the graph | ||
if (tree[PPID]) { | ||
tree[PPID].push(PID); | ||
} else { | ||
tree[PPID] = [PID]; | ||
} | ||
callback(null, list); | ||
} catch (err) { | ||
callback(err); | ||
} | ||
if (!found) { | ||
return done(new Error('No maching pid found')); | ||
} | ||
// Simplified BFS like tree visit | ||
var idx = 0; | ||
var pids = [pid]; | ||
while (idx < pids.length) { | ||
var cur = pids[idx++]; | ||
if (!tree[cur]) continue; | ||
var len = tree[cur].length; | ||
for (var j = 0; j < len; j++) { | ||
pids.push(tree[cur][j]); | ||
} | ||
delete tree[cur]; | ||
} | ||
pids.shift(); // Remove root | ||
done(null, pids); | ||
}); | ||
@@ -82,0 +45,0 @@ } |
@@ -7,7 +7,6 @@ 'use strict'; | ||
/** | ||
* Get the list of child pids of the given pid through the wmic command. | ||
* @param {Number} pid | ||
* @param {Function} done(err, tree) | ||
* Gets the list of all the pids of the system through the wmic command. | ||
* @param {Function} callback(err, list) | ||
*/ | ||
function wmic(pid, done) { | ||
function wmic(callback) { | ||
var args = ['PROCESS', 'get', 'ParentProcessId,ProcessId']; | ||
@@ -17,8 +16,11 @@ var options = {windowsHide: true, windowsVerbatimArguments: true}; | ||
if (err) { | ||
return done(err); | ||
callback(err); | ||
return; | ||
} | ||
if (code !== 0) { | ||
return done(new Error('pidtree wmic command exited with code ' + code)); | ||
callback(new Error('pidtree wmic command exited with code ' + code)); | ||
return; | ||
} | ||
// Example of stdout on Windows 10 | ||
// Example of stdout | ||
// | ||
@@ -28,47 +30,18 @@ // ParentProcessId ProcessId | ||
stdout = stdout.split(os.EOL); | ||
try { | ||
stdout = stdout.split(os.EOL); | ||
var found = false; | ||
var tree = {}; | ||
for (var i = 1; i < stdout.length; i++) { | ||
var line = stdout[i].trim().split(/\s+/); | ||
if (!line || line.length !== 2) { | ||
continue; | ||
var list = []; | ||
for (var i = 1; i < stdout.length; i++) { | ||
stdout[i] = stdout[i].trim(); | ||
if (!stdout[i]) continue; | ||
stdout[i] = stdout[i].split(/\s+/); | ||
stdout[i][0] = parseInt(stdout[i][0], 10); // PPID | ||
stdout[i][1] = parseInt(stdout[i][1], 10); // PID | ||
list.push(stdout[i]); | ||
} | ||
var PPID = parseInt(line[0], 10); | ||
var PID = parseInt(line[1], 10); | ||
if (pid === PID || pid === PPID) { | ||
found = true; | ||
} | ||
// Build the graph | ||
if (tree[PPID]) { | ||
tree[PPID].push(PID); | ||
} else { | ||
tree[PPID] = [PID]; | ||
} | ||
callback(null, list); | ||
} catch (err) { | ||
callback(err); | ||
} | ||
if (!found) { | ||
return done(new Error('No maching pid found')); | ||
} | ||
// Simplified BFS like tree visit | ||
var idx = 0; | ||
var pids = [pid]; | ||
while (idx < pids.length) { | ||
var cur = pids[idx++]; | ||
if (!tree[cur]) continue; | ||
var len = tree[cur].length; | ||
for (var j = 0; j < len; j++) { | ||
pids.push(tree[cur][j]); | ||
} | ||
delete tree[cur]; | ||
} | ||
pids.shift(); // Remove root | ||
done(null, pids); | ||
}); | ||
@@ -75,0 +48,0 @@ } |
{ | ||
"name": "pidtree", | ||
"version": "0.2.0", | ||
"version": "0.3.0", | ||
"description": "Cross platform children list of a PID", | ||
"license": "MIT", | ||
"homepage": "http://github.com/simonpri/pidtree#readme", | ||
"repository": "github:simonpri/pidtree", | ||
"homepage": "http://github.com/simonepri/pidtree#readme", | ||
"repository": "github:simonepri/pidtree", | ||
"bugs": { | ||
"url": "https://github.com/simonpri/pidtree/issues", | ||
"url": "https://github.com/simonepri/pidtree/issues", | ||
"email": "simonepri@outlook.com" | ||
@@ -16,3 +16,3 @@ }, | ||
], | ||
"keyboards": [ | ||
"keywords": [ | ||
"ps-tree", | ||
@@ -49,6 +49,8 @@ "ps", | ||
"test": "npm run lint&& nyc ava -m \"!*benchmark*\"", | ||
"bench": "ava -m \"*benchmark*\"" | ||
"bench": "ava -m \"*benchmark*\"", | ||
"coverage": "codecov" | ||
}, | ||
"devDependencies": { | ||
"ava": "*", | ||
"codecov": "*", | ||
"mockery": "^2.1.0", | ||
@@ -79,5 +81,6 @@ "np": "*", | ||
"prefer-arrow-callback": 0, | ||
"no-var": 0 | ||
"no-var": 0, | ||
"object-shorthand": 0 | ||
} | ||
} | ||
} |
@@ -70,6 +70,10 @@ <h1 align="center"> | ||
## Motivation | ||
The only package that does this simple but tricky job is [ps-tree][gh:ps-tree] | ||
but the project is unmaintained and furthermore the logic is wrong. | ||
## Synopsis | ||
This package is really similar to [ps-tree][gh:ps-tree] but is faster, safer and | ||
provides sub-children results. | ||
Furthermore ps-tree is [unmaintained][gh:ps-tree-um]. | ||
Uuh, and a fancy [CLI](#cli) is also available! | ||
## Usage | ||
@@ -92,12 +96,18 @@ | ||
// Get all the processes of the System on *nix | ||
pidtree(1, function (err, pids) { | ||
// Get all the processes of the System (-1 is a special value of this package) | ||
pidtree(-1, function (err, pids) { | ||
console.log(pids) | ||
// => [41,45,43,530,47,50, ..., 41241, 32] | ||
// => [530, 42, ..., 41241] | ||
}) | ||
// Include PPID in the results | ||
pidtree(1, {advanced: true}, function (err, pids) { | ||
console.log(pids) | ||
// => [{ppid: 1, pid: 530}, {ppid: 1, pid: 42}, ..., {ppid: 1, pid: 41241}] | ||
}) | ||
// If no callback is given it returns a promise instead | ||
const pids = await pidtree(1) | ||
console.log(pids) | ||
// => [41,45,43,530,47,50, ..., 41241, 32] | ||
// => [141, 42, ..., 15242] | ||
``` | ||
@@ -118,3 +128,4 @@ | ||
This package behave similarly to `pgrep -P` on \*unix | ||
<img src="https://github.com/simonepri/pidtree/raw/refactor/media/cli.gif" alt="pidtree cli" width="300" align="right"/> | ||
Show a tree of the processes inside your system inside your terminal. | ||
@@ -132,2 +143,9 @@ ```bash | ||
To display the output as a list, similar to the one produced from `pgrep -P $PID`, | ||
pass the `--list` flag. | ||
```bash | ||
npx pidtree --list | ||
``` | ||
## API | ||
@@ -137,7 +155,7 @@ | ||
## pidtree(pid, [options], [callback]) ⇒ <code>Promise.<Object></code> | ||
Get the list of child pids of the given pid. | ||
## pidtree(pid, [options], [callback]) ⇒ <code>[Promise.<Array.<Object>>]</code> | ||
Get the list of children pids of the given pid. | ||
**Kind**: global function | ||
**Returns**: <code>Promise.<Object></code> - Only when the callback is not provided. | ||
**Returns**: <code>Promise.<Array.<Object>></code> - Only when the callback is not provided. | ||
**Access**: public | ||
@@ -147,9 +165,9 @@ | ||
| --- | --- | --- | --- | | ||
| pid | <code>Number</code> \| <code>String</code> | | A pid. | | ||
| pid | <code>Number</code> \| <code>String</code> | | A pid. If -1 will return all the pids. | | ||
| [options] | <code>Object</code> | | Optional options object. | | ||
| [options.root] | <code>Boolean</code> | <code>false</code> | Include the provided pid in the list. | | ||
| [options.root] | <code>Boolean</code> | <code>false</code> | Include the provided pid in the list. Ignored if -1 is passed as pid. | | ||
| [callback] | <code>function</code> | | Called when the list is ready. If not provided a promise is returned instead. | | ||
## Related | ||
## Related | ||
- [pidusage][gh:pidusage] - | ||
@@ -159,2 +177,3 @@ Cross-platform process cpu % and memory usage of a PID | ||
## Authors | ||
- **Simone Primarosa** - [simonepri][github:simonepri] | ||
@@ -165,2 +184,3 @@ | ||
## License | ||
This project is licensed under the MIT License - see the [license][license] file for details. | ||
@@ -177,1 +197,2 @@ | ||
[gh:ps-tree]: https://github.com/indexzero/ps-tree | ||
[gh:ps-tree-um]: https://github.com/indexzero/ps-tree/issues/30 |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
18885
10
370
0
1
190
12
2