mirror of
				https://github.com/deployphp/action.git
				synced 2025-10-31 22:40:55 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			119 lines
		
	
	
	
		
			3.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			119 lines
		
	
	
	
		
			3.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
		
			Executable file
		
	
	
	
	
| '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);
 | |
|   }
 | |
| }
 |