Name

global.PsOutputParser

Description

Parses the output of a ps command.

Script

// Discovery

var PsOutputParser = Class.create();
PsOutputParser.prototype = {
  initialize: function() {
  },
  
  /**
   * Parses the given output from running ps (with at least the PID, PPID, and COMMAND columns), 
   * returning an array of running process objects with the following properties:
   *   pid:        the PID of the process
   *   ppid:       the PPID of the process
   *   name:       the name of the command (sans path)
   *   command:    the complete command (with path), but without the command's parameters
   *   parameters: the command's parameters (if any)
   *
   * Note: this method assumes that parameters always start with a ' -' string.
   */
  parse: function(output) {
      // parse the results from our ps output...
      var cols = [
          { header_matcher:/^PID$/,     prop_name:'pid',     last:false }, 
          { header_matcher:/^PPID$/,    prop_name:'ppid',    last:false }, 
          { header_matcher:/^C.*M.*D$/, prop_name:'command', last:true  }
      ];
      var ttp = new TabularTextParser();
      var rps = ttp.parse(output, cols);
      this.error_msg = ttp.error_msg;  // preserve any error messages we got from the parser...
      
      // now iterate over our found objects to split the command into name, command, and parameters...
      for (var i = 0; i < rps.length; i++) {
          var rp = rps[i];
          
  		// First check and see if we have a valid numerical value for pid and ppid
  		if (isNaN(rp.pid) || isNaN(rp.ppid)) {
  			rps.splice(i,1);
  			i--;
  			continue;
  		}

          // find the start of the parameters, if there are any
          // this is more challenging than it might appear, as all of the following are possible:
          //    /usr/bin/xxx -a
          //                 ^- parameters start
          //    /usr/bin/xxx /usr/bin/yyy -a
          //                 ^- parameters start
          //    /usr/bin abc/xxx -a
          //                     ^- parameters start
          //    /usr/bin/xxx yyy -a
          //                     ^- parameters start
          //    /usr/bin/xxx yyy ccc -a
          //                     ^- parameters start	
          var parts = rp.command.split(' ');
          var j;
          for (j = 1; j < parts.length; j++) {
              var c = parts[j].charAt(0);
              
              // if this part starts with something we can tell is a parameter, run with it...
              if ((c == '-') || (c == '/'))
                  break;
          }
          rp.command = parts.slice(0, j).join(' ');
          rp.parameters = parts.slice(j, parts.length).join(' ');
          
  		// For POSIX, the original process would typically have PID and PPID
  		// equal to 0. We need to fake a real root for later
  		if (rp.pid == rp.ppid)
  			rp.ppid = "1000000000" + rp.ppid;
  		
          // set the name...
          var name_index = rp.command.lastIndexOf('/');
          name_index = (name_index >= 0) ? name_index + 1 : 0;
          rp.name = rp.command.substring(name_index);
  		
  		//Trim up the whitespace
  		if(rp.name)
          	rp.name = rp.name.trim();
          if(rp.command)
          	rp.command = rp.command.trim();
  		if(rp.parameters)
  			rp.parameters = rp.parameters.trim();
  		if(rp.parameters.toLowerCase().includes("password")) {
  			rp.parameters = rp.parameters.replace(/password\s*=?\s*\S+/gmi,"******");
  		}
      }
      
      return rps;
  },
  
  /**
   * Filters out any kernel processes (processes that are child of the 
   * kernel thread).  These are not used in process classification.
   */
  filterKernelProcs: function(rps) {
  	// find the kernel thread pid, and filter it out
  	var kpid = -1;
  	for (var i = 0; i < rps.length; i++) {
  		if (rps[i].command == '[kthread]' || rps[i].command == '[kthreadd]') {	
  			kpid = rps[i].pid;
  			rps.splice(i,1);
  			break;
  		}
  	}
  	
  	if (kpid == -1)
  		return;
  	
  	// filter out any processes with ppid matching that of the kernel thread
  	var i = rps.length;
  	while (i--)
  		if (rps[i].ppid == kpid)
  			rps.splice(i,1);
  },

  type: 'PsOutputParser'
};

Sys ID

8ee1e1b49721300010cb1bd74b29755e

Offical Documentation

Official Docs: