123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- 'use strict';
- var spawn = require('child_process').spawn,
- es = require('event-stream');
- module.exports = function childrenOfPid(pid, callback) {
- var headers = null;
- if (typeof callback !== 'function') {
- throw new Error('childrenOfPid(pid, callback) expects callback');
- }
- if (typeof pid === 'number') {
- pid = pid.toString();
- }
- //
- // The `ps-tree` module behaves differently on *nix vs. Windows
- // by spawning different programs and parsing their output.
- //
- // Linux:
- // 1. " <defunct> " need to be striped
- // ```bash
- // $ ps -A -o comm,ppid,pid,stat
- // COMMAND PPID PID STAT
- // bbsd 2899 16958 Ss
- // watch <defunct> 1914 16964 Z
- // ps 20688 16965 R+
- // ```
- //
- // Win32:
- // 1. wmic PROCESS WHERE ParentProcessId=4604 GET Name,ParentProcessId,ProcessId,Status)
- // 2. The order of head columns is fixed
- // ```shell
- // > wmic PROCESS GET Name,ProcessId,ParentProcessId,Status
- // Name ParentProcessId ProcessId Status
- // System Idle Process 0 0
- // System 0 4
- // smss.exe 4 228
- // ```
- var processLister;
- if (process.platform === 'win32') {
- // See also: https://github.com/nodejs/node-v0.x-archive/issues/2318
- processLister = spawn('wmic.exe', ['PROCESS', 'GET', 'Name,ProcessId,ParentProcessId,Status']);
- } else {
- processLister = spawn('ps', ['-A', '-o', 'ppid,pid,stat,comm']);
- }
- es.connect(
- // spawn('ps', ['-A', '-o', 'ppid,pid,stat,comm']).stdout,
- processLister.stdout,
- es.split(),
- es.map(function (line, cb) { //this could parse alot of unix command output
- var columns = line.trim().split(/\s+/);
- if (!headers) {
- headers = columns;
- //
- // Rename Win32 header name, to as same as the linux, for compatible.
- //
- headers = headers.map(normalizeHeader);
- return cb();
- }
- var row = {};
- // For each header
- var h = headers.slice();
- while (h.length) {
- row[h.shift()] = h.length ? columns.shift() : columns.join(' ');
- }
- return cb(null, row);
- }),
- es.writeArray(function (err, ps) {
- var parents = {},
- children = [];
- parents[pid] = true;
- ps.forEach(function (proc) {
- if (parents[proc.PPID]) {
- parents[proc.PID] = true;
- children.push(proc)
- }
- });
- callback(null, children);
- })
- ).on('error', callback)
- }
- /**
- * Normalizes the given header `str` from the Windows
- * title to the *nix title.
- *
- * @param {string} str Header string to normalize
- */
- function normalizeHeader(str) {
- if (process.platform !== 'win32') {
- return str;
- }
- switch (str) {
- case 'Name':
- return 'COMMAND';
- break;
- case 'ParentProcessId':
- return 'PPID';
- break;
- case 'ProcessId':
- return 'PID';
- break;
- case 'Status':
- return 'STAT';
- break;
- default:
- throw new Error('Unknown process listing header: ' + str);
- }
- }
|