123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257 |
- 'use strict';
- // @ts-check
- // ==================================================================================
- // processes.js
- // ----------------------------------------------------------------------------------
- // Description: System Information - library
- // for Node.js
- // Copyright: (c) 2014 - 2022
- // Author: Sebastian Hildebrandt
- // ----------------------------------------------------------------------------------
- // License: MIT
- // ==================================================================================
- // 10. Processes
- // ----------------------------------------------------------------------------------
- const os = require('os');
- const fs = require('fs');
- const path = require('path');
- const exec = require('child_process').exec;
- const execSync = require('child_process').execSync;
- const util = require('./util');
- let _platform = process.platform;
- const _linux = (_platform === 'linux' || _platform === 'android');
- const _darwin = (_platform === 'darwin');
- const _windows = (_platform === 'win32');
- const _freebsd = (_platform === 'freebsd');
- const _openbsd = (_platform === 'openbsd');
- const _netbsd = (_platform === 'netbsd');
- const _sunos = (_platform === 'sunos');
- const _processes_cpu = {
- all: 0,
- all_utime: 0,
- all_stime: 0,
- list: {},
- ms: 0,
- result: {}
- };
- const _services_cpu = {
- all: 0,
- all_utime: 0,
- all_stime: 0,
- list: {},
- ms: 0,
- result: {}
- };
- const _process_cpu = {
- all: 0,
- all_utime: 0,
- all_stime: 0,
- list: {},
- ms: 0,
- result: {}
- };
- const _winStatusValues = {
- '0': 'unknown',
- '1': 'other',
- '2': 'ready',
- '3': 'running',
- '4': 'blocked',
- '5': 'suspended blocked',
- '6': 'suspended ready',
- '7': 'terminated',
- '8': 'stopped',
- '9': 'growing',
- };
- function parseTimeWin(time) {
- time = time || '';
- if (time) {
- return (time.substr(0, 4) + '-' + time.substr(4, 2) + '-' + time.substr(6, 2) + ' ' + time.substr(8, 2) + ':' + time.substr(10, 2) + ':' + time.substr(12, 2));
- } else {
- return '';
- }
- }
- function parseTimeUnix(time) {
- let result = time;
- let parts = time.replace(/ +/g, ' ').split(' ');
- if (parts.length === 5) {
- result = parts[4] + '-' + ('0' + ('JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC'.indexOf(parts[1].toUpperCase()) / 3 + 1)).slice(-2) + '-' + ('0' + parts[2]).slice(-2) + ' ' + parts[3];
- }
- return result;
- }
- // --------------------------
- // PS - services
- // pass a comma separated string with services to check (mysql, apache, postgresql, ...)
- // this function gives an array back, if the services are running.
- function services(srv, callback) {
- // fallback - if only callback is given
- if (util.isFunction(srv) && !callback) {
- callback = srv;
- srv = '';
- }
- return new Promise((resolve) => {
- process.nextTick(() => {
- if (typeof srv !== 'string') {
- if (callback) { callback([]); }
- return resolve([]);
- }
- if (srv) {
- let srvString = '';
- srvString.__proto__.toLowerCase = util.stringToLower;
- srvString.__proto__.replace = util.stringReplace;
- srvString.__proto__.trim = util.stringTrim;
- const s = util.sanitizeShellString(srv);
- for (let i = 0; i <= util.mathMin(s.length, 2000); i++) {
- if (!(s[i] === undefined)) {
- srvString = srvString + s[i];
- }
- }
- srvString = srvString.trim().toLowerCase().replace(/, /g, '|').replace(/,+/g, '|');
- if (srvString === '') {
- srvString = '*';
- }
- if (util.isPrototypePolluted() && srvString !== '*') {
- srvString = '------';
- }
- let srvs = srvString.split('|');
- let result = [];
- let dataSrv = [];
- // let allSrv = [];
- if (_linux || _freebsd || _openbsd || _netbsd || _darwin) {
- if ((_linux || _freebsd || _openbsd || _netbsd) && srvString === '*') {
- try {
- const tmpsrv = execSync('systemctl --type=service --no-legend 2> /dev/null').toString().split('\n');
- srvs = [];
- for (const s of tmpsrv) {
- const name = s.split('.service')[0];
- if (name) {
- srvs.push(name);
- }
- }
- srvString = srvs.join('|');
- } catch (d) {
- try {
- srvString = '';
- const tmpsrv = execSync('service --status-all 2> /dev/null').toString().split('\n');
- for (const s of tmpsrv) {
- const parts = s.split(']');
- if (parts.length === 2) {
- srvString += (srvString !== '' ? '|' : '') + parts[1].trim();
- // allSrv.push({ name: parts[1].trim(), running: parts[0].indexOf('+') > 0 });
- }
- }
- srvs = srvString.split('|');
- } catch (e) {
- try {
- const srvStr = execSync('ls /etc/init.d/ -m 2> /dev/null').toString().split('\n').join('');
- srvString = '';
- if (srvStr) {
- const tmpsrv = srvStr.split(',');
- for (const s of tmpsrv) {
- const name = s.trim();
- if (name) {
- srvString += (srvString !== '' ? '|' : '') + name;
- // allSrv.push({ name: name, running: null });
- }
- }
- srvs = srvString.split('|');
- }
- } catch (f) {
- // allSrv = [];
- srvString = '';
- srvs = [];
- }
- }
- }
- }
- if ((_darwin) && srvString === '*') { // service enumeration not yet suported on mac OS
- if (callback) { callback(result); }
- resolve(result);
- }
- let args = (_darwin) ? ['-caxo', 'pcpu,pmem,pid,command'] : ['-axo', 'pcpu,pmem,pid,command'];
- if (srvString !== '' && srvs.length > 0) {
- util.execSafe('ps', args).then((stdout) => {
- if (stdout) {
- let lines = stdout.replace(/ +/g, ' ').replace(/,+/g, '.').split('\n');
- srvs.forEach(function (srv) {
- let ps;
- if (_darwin) {
- ps = lines.filter(function (e) {
- return (e.toLowerCase().indexOf(srv) !== -1);
- });
- } else {
- ps = lines.filter(function (e) {
- return (e.toLowerCase().indexOf(' ' + srv + ':') !== -1) || (e.toLowerCase().indexOf('/' + srv) !== -1);
- });
- }
- // let singleSrv = allSrv.filter(item => { return item.name === srv; });
- const pids = [];
- for (const p of ps) {
- const pid = p.trim().split(' ')[2];
- if (pid) {
- pids.push(parseInt(pid, 10));
- }
- }
- result.push({
- name: srv,
- // running: (allSrv.length && singleSrv.length && singleSrv[0].running !== null ? singleSrv[0].running : ps.length > 0),
- running: ps.length > 0,
- startmode: '',
- pids: pids,
- cpu: parseFloat((ps.reduce(function (pv, cv) {
- return pv + parseFloat(cv.trim().split(' ')[0]);
- }, 0)).toFixed(2)),
- mem: parseFloat((ps.reduce(function (pv, cv) {
- return pv + parseFloat(cv.trim().split(' ')[1]);
- }, 0)).toFixed(2))
- });
- });
- if (_linux) {
- // calc process_cpu - ps is not accurate in linux!
- let cmd = 'cat /proc/stat | grep "cpu "';
- for (let i in result) {
- for (let j in result[i].pids) {
- cmd += (';cat /proc/' + result[i].pids[j] + '/stat');
- }
- }
- exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
- let curr_processes = stdout.toString().split('\n');
- // first line (all - /proc/stat)
- let all = parseProcStat(curr_processes.shift());
- // process
- let list_new = {};
- let resultProcess = {};
- for (let i = 0; i < curr_processes.length; i++) {
- resultProcess = calcProcStatLinux(curr_processes[i], all, _services_cpu);
- if (resultProcess.pid) {
- let listPos = -1;
- for (let i in result) {
- for (let j in result[i].pids) {
- if (parseInt(result[i].pids[j]) === parseInt(resultProcess.pid)) {
- listPos = i;
- }
- }
- }
- if (listPos >= 0) {
- result[listPos].cpu += resultProcess.cpuu + resultProcess.cpus;
- }
- // save new values
- list_new[resultProcess.pid] = {
- cpuu: resultProcess.cpuu,
- cpus: resultProcess.cpus,
- utime: resultProcess.utime,
- stime: resultProcess.stime,
- cutime: resultProcess.cutime,
- cstime: resultProcess.cstime
- };
- }
- }
- // store old values
- _services_cpu.all = all;
- // _services_cpu.list = list_new;
- _services_cpu.list = Object.assign({}, list_new);
- _services_cpu.ms = Date.now() - _services_cpu.ms;
- // _services_cpu.result = result;
- _services_cpu.result = Object.assign({}, result);
- if (callback) { callback(result); }
- resolve(result);
- });
- } else {
- if (callback) { callback(result); }
- resolve(result);
- }
- } else {
- args = ['-o', 'comm'];
- util.execSafe('ps', args).then((stdout) => {
- if (stdout) {
- let lines = stdout.replace(/ +/g, ' ').replace(/,+/g, '.').split('\n');
- srvs.forEach(function (srv) {
- let ps = lines.filter(function (e) {
- return e.indexOf(srv) !== -1;
- });
- result.push({
- name: srv,
- running: ps.length > 0,
- startmode: '',
- cpu: 0,
- mem: 0
- });
- });
- if (callback) { callback(result); }
- resolve(result);
- } else {
- srvs.forEach(function (srv) {
- result.push({
- name: srv,
- running: false,
- startmode: '',
- cpu: 0,
- mem: 0
- });
- });
- if (callback) { callback(result); }
- resolve(result);
- }
- });
- }
- });
- } else {
- if (callback) { callback(result); }
- resolve(result);
- }
- }
- if (_windows) {
- try {
- let wincommand = 'Get-WmiObject Win32_Service';
- if (srvs[0] !== '*') {
- wincommand += ' -Filter "';
- for (let i = 0; i < srvs.length; i++) {
- wincommand += `Name='${srvs[i]}' or `;
- }
- wincommand = `${wincommand.slice(0, -4)}"`;
- }
- wincommand += ' | select Name,Caption,Started,StartMode,ProcessId | fl';
- util.powerShell(wincommand).then((stdout, error) => {
- if (!error) {
- let serviceSections = stdout.split(/\n\s*\n/);
- for (let i = 0; i < serviceSections.length; i++) {
- if (serviceSections[i].trim() !== '') {
- let lines = serviceSections[i].trim().split('\r\n');
- let srvName = util.getValue(lines, 'Name', ':', true).toLowerCase();
- let srvCaption = util.getValue(lines, 'Caption', ':', true).toLowerCase();
- let started = util.getValue(lines, 'Started', ':', true);
- let startMode = util.getValue(lines, 'StartMode', ':', true);
- let pid = util.getValue(lines, 'ProcessId', ':', true);
- if (srvString === '*' || srvs.indexOf(srvName) >= 0 || srvs.indexOf(srvCaption) >= 0) {
- result.push({
- name: srvName,
- running: (started.toLowerCase() === 'true'),
- startmode: startMode,
- pids: [pid],
- cpu: 0,
- mem: 0
- });
- dataSrv.push(srvName);
- dataSrv.push(srvCaption);
- }
- }
- }
- if (srvString !== '*') {
- let srvsMissing = srvs.filter(function (e) {
- return dataSrv.indexOf(e) === -1;
- });
- srvsMissing.forEach(function (srvName) {
- result.push({
- name: srvName,
- running: false,
- startmode: '',
- pids: [],
- cpu: 0,
- mem: 0
- });
- });
- }
- if (callback) { callback(result); }
- resolve(result);
- } else {
- srvs.forEach(function (srvName) {
- result.push({
- name: srvName,
- running: false,
- startmode: '',
- cpu: 0,
- mem: 0
- });
- });
- if (callback) { callback(result); }
- resolve(result);
- }
- });
- } catch (e) {
- if (callback) { callback(result); }
- resolve(result);
- }
- }
- } else {
- if (callback) { callback([]); }
- resolve([]);
- }
- });
- });
- }
- exports.services = services;
- function parseProcStat(line) {
- let parts = line.replace(/ +/g, ' ').split(' ');
- let user = (parts.length >= 2 ? parseInt(parts[1]) : 0);
- let nice = (parts.length >= 3 ? parseInt(parts[2]) : 0);
- let system = (parts.length >= 4 ? parseInt(parts[3]) : 0);
- let idle = (parts.length >= 5 ? parseInt(parts[4]) : 0);
- let iowait = (parts.length >= 6 ? parseInt(parts[5]) : 0);
- let irq = (parts.length >= 7 ? parseInt(parts[6]) : 0);
- let softirq = (parts.length >= 8 ? parseInt(parts[7]) : 0);
- let steal = (parts.length >= 9 ? parseInt(parts[8]) : 0);
- let guest = (parts.length >= 10 ? parseInt(parts[9]) : 0);
- let guest_nice = (parts.length >= 11 ? parseInt(parts[10]) : 0);
- return user + nice + system + idle + iowait + irq + softirq + steal + guest + guest_nice;
- }
- function calcProcStatLinux(line, all, _cpu_old) {
- let statparts = line.replace(/ +/g, ' ').split(')');
- if (statparts.length >= 2) {
- let parts = statparts[1].split(' ');
- if (parts.length >= 16) {
- let pid = parseInt(statparts[0].split(' ')[0]);
- let utime = parseInt(parts[12]);
- let stime = parseInt(parts[13]);
- let cutime = parseInt(parts[14]);
- let cstime = parseInt(parts[15]);
- // calc
- let cpuu = 0;
- let cpus = 0;
- if (_cpu_old.all > 0 && _cpu_old.list[pid]) {
- cpuu = (utime + cutime - _cpu_old.list[pid].utime - _cpu_old.list[pid].cutime) / (all - _cpu_old.all) * 100; // user
- cpus = (stime + cstime - _cpu_old.list[pid].stime - _cpu_old.list[pid].cstime) / (all - _cpu_old.all) * 100; // system
- } else {
- cpuu = (utime + cutime) / (all) * 100; // user
- cpus = (stime + cstime) / (all) * 100; // system
- }
- return {
- pid: pid,
- utime: utime,
- stime: stime,
- cutime: cutime,
- cstime: cstime,
- cpuu: cpuu,
- cpus: cpus
- };
- } else {
- return {
- pid: 0,
- utime: 0,
- stime: 0,
- cutime: 0,
- cstime: 0,
- cpuu: 0,
- cpus: 0
- };
- }
- } else {
- return {
- pid: 0,
- utime: 0,
- stime: 0,
- cutime: 0,
- cstime: 0,
- cpuu: 0,
- cpus: 0
- };
- }
- }
- function calcProcStatWin(procStat, all, _cpu_old) {
- // calc
- let cpuu = 0;
- let cpus = 0;
- if (_cpu_old.all > 0 && _cpu_old.list[procStat.pid]) {
- cpuu = (procStat.utime - _cpu_old.list[procStat.pid].utime) / (all - _cpu_old.all) * 100; // user
- cpus = (procStat.stime - _cpu_old.list[procStat.pid].stime) / (all - _cpu_old.all) * 100; // system
- } else {
- cpuu = (procStat.utime) / (all) * 100; // user
- cpus = (procStat.stime) / (all) * 100; // system
- }
- return {
- pid: procStat.pid,
- utime: cpuu > 0 ? procStat.utime : 0,
- stime: cpus > 0 ? procStat.stime : 0,
- cpuu: cpuu > 0 ? cpuu : 0,
- cpus: cpus > 0 ? cpus : 0
- };
- }
- // --------------------------
- // running processes
- function processes(callback) {
- let parsedhead = [];
- function getName(command) {
- command = command || '';
- let result = command.split(' ')[0];
- if (result.substr(-1) === ':') {
- result = result.substr(0, result.length - 1);
- }
- if (result.substr(0, 1) !== '[') {
- let parts = result.split('/');
- if (isNaN(parseInt(parts[parts.length - 1]))) {
- result = parts[parts.length - 1];
- } else {
- result = parts[0];
- }
- }
- return result;
- }
- function parseLine(line) {
- let offset = 0;
- let offset2 = 0;
- function checkColumn(i) {
- offset = offset2;
- if (parsedhead[i]) {
- offset2 = line.substring(parsedhead[i].to + offset, 10000).indexOf(' ');
- } else {
- offset2 = 10000;
- }
- }
- checkColumn(0);
- const pid = parseInt(line.substring(parsedhead[0].from + offset, parsedhead[0].to + offset2));
- checkColumn(1);
- const ppid = parseInt(line.substring(parsedhead[1].from + offset, parsedhead[1].to + offset2));
- checkColumn(2);
- const cpu = parseFloat(line.substring(parsedhead[2].from + offset, parsedhead[2].to + offset2).replace(/,/g, '.'));
- checkColumn(3);
- const mem = parseFloat(line.substring(parsedhead[3].from + offset, parsedhead[3].to + offset2).replace(/,/g, '.'));
- checkColumn(4);
- const priority = parseInt(line.substring(parsedhead[4].from + offset, parsedhead[4].to + offset2));
- checkColumn(5);
- const vsz = parseInt(line.substring(parsedhead[5].from + offset, parsedhead[5].to + offset2));
- checkColumn(6);
- const rss = parseInt(line.substring(parsedhead[6].from + offset, parsedhead[6].to + offset2));
- checkColumn(7);
- const nice = parseInt(line.substring(parsedhead[7].from + offset, parsedhead[7].to + offset2)) || 0;
- checkColumn(8);
- const started = parseTimeUnix(line.substring(parsedhead[8].from + offset, parsedhead[8].to + offset2).trim());
- checkColumn(9);
- let state = line.substring(parsedhead[9].from + offset, parsedhead[9].to + offset2).trim();
- state = (state[0] === 'R' ? 'running' : (state[0] === 'S' ? 'sleeping' : (state[0] === 'T' ? 'stopped' : (state[0] === 'W' ? 'paging' : (state[0] === 'X' ? 'dead' : (state[0] === 'Z' ? 'zombie' : ((state[0] === 'D' || state[0] === 'U') ? 'blocked' : 'unknown')))))));
- checkColumn(10);
- let tty = line.substring(parsedhead[10].from + offset, parsedhead[10].to + offset2).trim();
- if (tty === '?' || tty === '??') { tty = ''; }
- checkColumn(11);
- const user = line.substring(parsedhead[11].from + offset, parsedhead[11].to + offset2).trim();
- checkColumn(12);
- let cmdPath = '';
- let command = '';
- let params = '';
- let fullcommand = line.substring(parsedhead[12].from + offset, parsedhead[12].to + offset2).trim();
- if (fullcommand.substr(fullcommand.length - 1) === ']') { fullcommand = fullcommand.slice(0, -1); }
- if (fullcommand.substr(0, 1) === '[') { command = fullcommand.substring(1); }
- else {
- // try to figure out where parameter starts
- let firstParamPos = fullcommand.indexOf(' -');
- let firstParamPathPos = fullcommand.indexOf(' /');
- firstParamPos = (firstParamPos >= 0 ? firstParamPos : 10000);
- firstParamPathPos = (firstParamPathPos >= 0 ? firstParamPathPos : 10000);
- const firstPos = Math.min(firstParamPos, firstParamPathPos);
- let tmpCommand = fullcommand.substr(0, firstPos);
- const tmpParams = fullcommand.substr(firstPos);
- const lastSlashPos = tmpCommand.lastIndexOf('/');
- if (lastSlashPos >= 0) {
- cmdPath = tmpCommand.substr(0, lastSlashPos);
- tmpCommand = tmpCommand.substr(lastSlashPos + 1);
- }
- if (firstPos === 10000 && tmpCommand.indexOf(' ') > -1) {
- const parts = tmpCommand.split(' ');
- if (fs.existsSync(path.join(cmdPath, parts[0]))) {
- command = parts.shift();
- params = (parts.join(' ') + ' ' + tmpParams).trim();
- } else {
- command = tmpCommand.trim();
- params = tmpParams.trim();
- }
- } else {
- command = tmpCommand.trim();
- params = tmpParams.trim();
- }
- }
- return ({
- pid: pid,
- parentPid: ppid,
- name: _linux ? getName(command) : command,
- cpu: cpu,
- cpuu: 0,
- cpus: 0,
- mem: mem,
- priority: priority,
- memVsz: vsz,
- memRss: rss,
- nice: nice,
- started: started,
- state: state,
- tty: tty,
- user: user,
- command: command,
- params: params,
- path: cmdPath
- });
- }
- function parseProcesses(lines) {
- let result = [];
- if (lines.length > 1) {
- let head = lines[0];
- parsedhead = util.parseHead(head, 8);
- lines.shift();
- lines.forEach(function (line) {
- if (line.trim() !== '') {
- result.push(parseLine(line));
- }
- });
- }
- return result;
- }
- function parseProcesses2(lines) {
- function formatDateTime(time) {
- const month = ('0' + (time.getMonth() + 1).toString()).substr(-2);
- const year = time.getFullYear().toString();
- const day = ('0' + time.getDay().toString()).substr(-2);
- const hours = time.getHours().toString();
- const mins = time.getMinutes().toString();
- const secs = ('0' + time.getSeconds().toString()).substr(-2);
- return (year + '-' + month + '-' + day + ' ' + hours + ':' + mins + ':' + secs);
- }
- let result = [];
- lines.forEach(function (line) {
- if (line.trim() !== '') {
- line = line.trim().replace(/ +/g, ' ').replace(/,+/g, '.');
- const parts = line.split(' ');
- const command = parts.slice(9).join(' ');
- const pmem = parseFloat((1.0 * parseInt(parts[3]) * 1024 / os.totalmem()).toFixed(1));
- const elapsed_parts = parts[5].split(':');
- const started = formatDateTime(new Date(Date.now() - (elapsed_parts.length > 1 ? (elapsed_parts[0] * 60 + elapsed_parts[1]) * 1000 : elapsed_parts[0] * 1000)));
- result.push({
- pid: parseInt(parts[0]),
- parentPid: parseInt(parts[1]),
- name: getName(command),
- cpu: 0,
- cpuu: 0,
- cpus: 0,
- mem: pmem,
- priority: 0,
- memVsz: parseInt(parts[2]),
- memRss: parseInt(parts[3]),
- nice: parseInt(parts[4]),
- started: started,
- state: (parts[6] === 'R' ? 'running' : (parts[6] === 'S' ? 'sleeping' : (parts[6] === 'T' ? 'stopped' : (parts[6] === 'W' ? 'paging' : (parts[6] === 'X' ? 'dead' : (parts[6] === 'Z' ? 'zombie' : ((parts[6] === 'D' || parts[6] === 'U') ? 'blocked' : 'unknown'))))))),
- tty: parts[7],
- user: parts[8],
- command: command
- });
- }
- });
- return result;
- }
- return new Promise((resolve) => {
- process.nextTick(() => {
- let result = {
- all: 0,
- running: 0,
- blocked: 0,
- sleeping: 0,
- unknown: 0,
- list: []
- };
- let cmd = '';
- if ((_processes_cpu.ms && Date.now() - _processes_cpu.ms >= 500) || _processes_cpu.ms === 0) {
- if (_linux || _freebsd || _openbsd || _netbsd || _darwin || _sunos) {
- if (_linux) { cmd = 'export LC_ALL=C; ps -axo pid:11,ppid:11,pcpu:6,pmem:6,pri:5,vsz:11,rss:11,ni:5,lstart:30,state:5,tty:15,user:20,command; unset LC_ALL'; }
- if (_freebsd || _openbsd || _netbsd) { cmd = 'export LC_ALL=C; ps -axo pid,ppid,pcpu,pmem,pri,vsz,rss,ni,lstart,state,tty,user,command; unset LC_ALL'; }
- if (_darwin) { cmd = 'ps -axo pid,ppid,pcpu,pmem,pri,vsz=xxx_fake_title,rss=fake_title2,nice,lstart,state,tty,user,command -r'; }
- if (_sunos) { cmd = 'ps -Ao pid,ppid,pcpu,pmem,pri,vsz,rss,nice,stime,s,tty,user,comm'; }
- exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
- if (!error && stdout.toString().trim()) {
- result.list = (parseProcesses(stdout.toString().split('\n'))).slice();
- result.all = result.list.length;
- result.running = result.list.filter(function (e) {
- return e.state === 'running';
- }).length;
- result.blocked = result.list.filter(function (e) {
- return e.state === 'blocked';
- }).length;
- result.sleeping = result.list.filter(function (e) {
- return e.state === 'sleeping';
- }).length;
- if (_linux) {
- // calc process_cpu - ps is not accurate in linux!
- cmd = 'cat /proc/stat | grep "cpu "';
- for (let i = 0; i < result.list.length; i++) {
- cmd += (';cat /proc/' + result.list[i].pid + '/stat');
- }
- exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
- let curr_processes = stdout.toString().split('\n');
- // first line (all - /proc/stat)
- let all = parseProcStat(curr_processes.shift());
- // process
- let list_new = {};
- let resultProcess = {};
- for (let i = 0; i < curr_processes.length; i++) {
- resultProcess = calcProcStatLinux(curr_processes[i], all, _processes_cpu);
- if (resultProcess.pid) {
- // store pcpu in outer array
- let listPos = result.list.map(function (e) { return e.pid; }).indexOf(resultProcess.pid);
- if (listPos >= 0) {
- result.list[listPos].cpu = resultProcess.cpuu + resultProcess.cpus;
- result.list[listPos].cpuu = resultProcess.cpuu;
- result.list[listPos].cpus = resultProcess.cpus;
- }
- // save new values
- list_new[resultProcess.pid] = {
- cpuu: resultProcess.cpuu,
- cpus: resultProcess.cpus,
- utime: resultProcess.utime,
- stime: resultProcess.stime,
- cutime: resultProcess.cutime,
- cstime: resultProcess.cstime
- };
- }
- }
- // store old values
- _processes_cpu.all = all;
- // _processes_cpu.list = list_new;
- _processes_cpu.list = Object.assign({}, list_new);
- _processes_cpu.ms = Date.now() - _processes_cpu.ms;
- // _processes_cpu.result = result;
- _processes_cpu.result = Object.assign({}, result);
- if (callback) { callback(result); }
- resolve(result);
- });
- } else {
- if (callback) { callback(result); }
- resolve(result);
- }
- } else {
- cmd = 'ps -o pid,ppid,vsz,rss,nice,etime,stat,tty,user,comm';
- if (_sunos) {
- cmd = 'ps -o pid,ppid,vsz,rss,nice,etime,s,tty,user,comm';
- }
- exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
- if (!error) {
- let lines = stdout.toString().split('\n');
- lines.shift();
- result.list = parseProcesses2(lines).slice();
- result.all = result.list.length;
- result.running = result.list.filter(function (e) {
- return e.state === 'running';
- }).length;
- result.blocked = result.list.filter(function (e) {
- return e.state === 'blocked';
- }).length;
- result.sleeping = result.list.filter(function (e) {
- return e.state === 'sleeping';
- }).length;
- if (callback) { callback(result); }
- resolve(result);
- } else {
- if (callback) { callback(result); }
- resolve(result);
- }
- });
- }
- });
- } else if (_windows) {
- try {
- util.powerShell('Get-WmiObject Win32_Process | select ProcessId,ParentProcessId,ExecutionState,Caption,CommandLine,ExecutablePath,UserModeTime,KernelModeTime,WorkingSetSize,Priority,PageFileUsage,CreationDate | fl').then((stdout, error) => {
- if (!error) {
- let processSections = stdout.split(/\n\s*\n/);
- let procs = [];
- let procStats = [];
- let list_new = {};
- let allcpuu = 0;
- let allcpus = 0;
- // let allcpuu = _processes_cpu.all_utime;
- // let allcpus = _processes_cpu.all_stime;
- for (let i = 0; i < processSections.length; i++) {
- if (processSections[i].trim() !== '') {
- let lines = processSections[i].trim().split('\r\n');
- let pid = parseInt(util.getValue(lines, 'ProcessId', ':', true), 10);
- let parentPid = parseInt(util.getValue(lines, 'ParentProcessId', ':', true), 10);
- let statusValue = util.getValue(lines, 'ExecutionState', ':');
- let name = util.getValue(lines, 'Caption', ':', true);
- let commandLine = util.getValue(lines, 'CommandLine', ':', true);
- let commandPath = util.getValue(lines, 'ExecutablePath', ':', true);
- let utime = parseInt(util.getValue(lines, 'UserModeTime', ':', true), 10);
- let stime = parseInt(util.getValue(lines, 'KernelModeTime', ':', true), 10);
- let memw = parseInt(util.getValue(lines, 'WorkingSetSize', ':', true), 10);
- allcpuu = allcpuu + utime;
- allcpus = allcpus + stime;
- // allcpuu += utime - (_processes_cpu.list[pid] ? _processes_cpu.list[pid].utime : 0);
- // allcpus += stime - (_processes_cpu.list[pid] ? _processes_cpu.list[pid].stime : 0);
- result.all++;
- if (!statusValue) { result.unknown++; }
- if (statusValue === '3') { result.running++; }
- if (statusValue === '4' || statusValue === '5') { result.blocked++; }
- procStats.push({
- pid: pid,
- utime: utime,
- stime: stime,
- cpu: 0,
- cpuu: 0,
- cpus: 0,
- });
- procs.push({
- pid: pid,
- parentPid: parentPid,
- name: name,
- cpu: 0,
- cpuu: 0,
- cpus: 0,
- mem: memw / os.totalmem() * 100,
- priority: parseInt(util.getValue(lines, 'Priority', ':', true), 10),
- memVsz: parseInt(util.getValue(lines, 'PageFileUsage', ':', true), 10),
- memRss: Math.floor(parseInt(util.getValue(lines, 'WorkingSetSize', ':', true), 10) / 1024),
- nice: 0,
- started: parseTimeWin(util.getValue(lines, 'CreationDate', ':', true)),
- state: (!statusValue ? _winStatusValues[0] : _winStatusValues[statusValue]),
- tty: '',
- user: '',
- command: commandLine || name,
- path: commandPath,
- params: ''
- });
- }
- }
- result.sleeping = result.all - result.running - result.blocked - result.unknown;
- result.list = procs;
- for (let i = 0; i < procStats.length; i++) {
- let resultProcess = calcProcStatWin(procStats[i], allcpuu + allcpus, _processes_cpu);
- // store pcpu in outer array
- let listPos = result.list.map(function (e) { return e.pid; }).indexOf(resultProcess.pid);
- if (listPos >= 0) {
- result.list[listPos].cpu = resultProcess.cpuu + resultProcess.cpus;
- result.list[listPos].cpuu = resultProcess.cpuu;
- result.list[listPos].cpus = resultProcess.cpus;
- }
- // save new values
- list_new[resultProcess.pid] = {
- cpuu: resultProcess.cpuu,
- cpus: resultProcess.cpus,
- utime: resultProcess.utime,
- stime: resultProcess.stime
- };
- }
- // store old values
- _processes_cpu.all = allcpuu + allcpus;
- _processes_cpu.all_utime = allcpuu;
- _processes_cpu.all_stime = allcpus;
- // _processes_cpu.list = list_new;
- _processes_cpu.list = Object.assign({}, list_new);
- _processes_cpu.ms = Date.now() - _processes_cpu.ms;
- // _processes_cpu.result = result;
- _processes_cpu.result = Object.assign({}, result);
- }
- if (callback) {
- callback(result);
- }
- resolve(result);
- });
- } catch (e) {
- if (callback) { callback(result); }
- resolve(result);
- }
- } else {
- if (callback) { callback(result); }
- resolve(result);
- }
- } else {
- if (callback) { callback(_processes_cpu.result); }
- resolve(_processes_cpu.result);
- }
- });
- });
- }
- exports.processes = processes;
- // --------------------------
- // PS - process load
- // get detailed information about a certain process
- // (PID, CPU-Usage %, Mem-Usage %)
- function processLoad(proc, callback) {
- // fallback - if only callback is given
- if (util.isFunction(proc) && !callback) {
- callback = proc;
- proc = '';
- }
- return new Promise((resolve) => {
- process.nextTick(() => {
- proc = proc || '';
- if (typeof proc !== 'string') {
- if (callback) { callback([]); }
- return resolve([]);
- }
- let processesString = '';
- processesString.__proto__.toLowerCase = util.stringToLower;
- processesString.__proto__.replace = util.stringReplace;
- processesString.__proto__.trim = util.stringTrim;
- const s = util.sanitizeShellString(proc);
- for (let i = 0; i <= util.mathMin(s.length, 2000); i++) {
- if (!(s[i] === undefined)) {
- processesString = processesString + s[i];
- }
- }
- processesString = processesString.trim().toLowerCase().replace(/, /g, '|').replace(/,+/g, '|');
- if (processesString === '') {
- processesString = '*';
- }
- if (util.isPrototypePolluted() && processesString !== '*') {
- processesString = '------';
- }
- let processes = processesString.split('|');
- let result = [];
- const procSanitized = util.isPrototypePolluted() ? '' : util.sanitizeShellString(proc);
- // from here new
- // let result = {
- // 'proc': procSanitized,
- // 'pid': null,
- // 'cpu': 0,
- // 'mem': 0
- // };
- if (procSanitized && processes.length && processes[0] !== '------') {
- if (_windows) {
- try {
- util.powerShell('Get-WmiObject Win32_Process | select ProcessId,Caption,UserModeTime,KernelModeTime,WorkingSetSize | fl').then((stdout, error) => {
- if (!error) {
- let processSections = stdout.split(/\n\s*\n/);
- let procStats = [];
- let list_new = {};
- let allcpuu = 0;
- let allcpus = 0;
- // let allcpuu = _process_cpu.all_utime;
- // let allcpus = _process_cpu.all_stime;
- // go through all processes
- for (let i = 0; i < processSections.length; i++) {
- if (processSections[i].trim() !== '') {
- let lines = processSections[i].trim().split('\r\n');
- let pid = parseInt(util.getValue(lines, 'ProcessId', ':', true), 10);
- let name = util.getValue(lines, 'Caption', ':', true);
- let utime = parseInt(util.getValue(lines, 'UserModeTime', ':', true), 10);
- let stime = parseInt(util.getValue(lines, 'KernelModeTime', ':', true), 10);
- let mem = parseInt(util.getValue(lines, 'WorkingSetSize', ':', true), 10);
- allcpuu = allcpuu + utime;
- allcpus = allcpus + stime;
- // allcpuu += utime - (_process_cpu.list[pid] ? _process_cpu.list[pid].utime : 0);
- // allcpus += stime - (_process_cpu.list[pid] ? _process_cpu.list[pid].stime : 0);
- procStats.push({
- pid: pid,
- name,
- utime: utime,
- stime: stime,
- cpu: 0,
- cpuu: 0,
- cpus: 0,
- mem
- });
- let pname = '';
- let inList = false;
- processes.forEach(function (proc) {
- // console.log(proc)
- // console.log(item)
- // inList = inList || item.name.toLowerCase() === proc.toLowerCase();
- if (name.toLowerCase().indexOf(proc.toLowerCase()) >= 0 && !inList) {
- inList = true;
- pname = proc;
- }
- });
- if (processesString === '*' || inList) {
- let processFound = false;
- result.forEach(function (item) {
- if (item.proc.toLowerCase() === pname.toLowerCase()) {
- item.pids.push(pid);
- item.mem += mem / os.totalmem() * 100;
- processFound = true;
- }
- });
- if (!processFound) {
- result.push({
- proc: pname,
- pid: pid,
- pids: [pid],
- cpu: 0,
- mem: mem / os.totalmem() * 100
- });
- }
- }
- }
- }
- // add missing processes
- if (processesString !== '*') {
- let processesMissing = processes.filter(function (name) {
- // return procStats.filter(function(item) { return item.name.toLowerCase() === name }).length === 0;
- return procStats.filter(function (item) { return item.name.toLowerCase().indexOf(name) >= 0; }).length === 0;
- });
- processesMissing.forEach(function (procName) {
- result.push({
- proc: procName,
- pid: null,
- pids: [],
- cpu: 0,
- mem: 0
- });
- });
- }
- // calculate proc stats for each proc
- for (let i = 0; i < procStats.length; i++) {
- let resultProcess = calcProcStatWin(procStats[i], allcpuu + allcpus, _process_cpu);
- let listPos = -1;
- for (let j = 0; j < result.length; j++) {
- if (result[j].pid === resultProcess.pid || result[j].pids.indexOf(resultProcess.pid) >= 0) { listPos = j; }
- }
- if (listPos >= 0) {
- result[listPos].cpu += resultProcess.cpuu + resultProcess.cpus;
- }
- // save new values
- list_new[resultProcess.pid] = {
- cpuu: resultProcess.cpuu,
- cpus: resultProcess.cpus,
- utime: resultProcess.utime,
- stime: resultProcess.stime
- };
- }
- // store old values
- _process_cpu.all = allcpuu + allcpus;
- _process_cpu.all_utime = allcpuu;
- _process_cpu.all_stime = allcpus;
- // _process_cpu.list = list_new;
- _process_cpu.list = Object.assign({}, list_new);
- _process_cpu.ms = Date.now() - _process_cpu.ms;
- _process_cpu.result = JSON.parse(JSON.stringify(result));
- if (callback) {
- callback(result);
- }
- resolve(result);
- }
- });
- } catch (e) {
- if (callback) { callback(result); }
- resolve(result);
- }
- }
- if (_darwin || _linux || _freebsd || _openbsd || _netbsd) {
- const params = ['-axo', 'pid,pcpu,pmem,comm'];
- util.execSafe('ps', params).then((stdout) => {
- if (stdout) {
- let procStats = [];
- let lines = stdout.toString().split('\n').filter(function (line) {
- if (processesString === '*') { return true; }
- if (line.toLowerCase().indexOf('grep') !== -1) { return false; } // remove this??
- let found = false;
- processes.forEach(function (item) {
- found = found || (line.toLowerCase().indexOf(item.toLowerCase()) >= 0);
- });
- return found;
- });
- lines.forEach(function (line) {
- let data = line.trim().replace(/ +/g, ' ').split(' ');
- if (data.length > 3) {
- procStats.push({
- name: data[3].substring(data[3].lastIndexOf('/') + 1),
- pid: parseInt(data[0]) || 0,
- cpu: parseFloat(data[1].replace(',', '.')),
- mem: parseFloat(data[2].replace(',', '.'))
- });
- }
- });
- procStats.forEach(function (item) {
- let listPos = -1;
- let inList = false;
- let name = '';
- for (let j = 0; j < result.length; j++) {
- // if (result[j].proc.toLowerCase() === item.name.toLowerCase()) {
- // if (result[j].proc.toLowerCase().indexOf(item.name.toLowerCase()) >= 0) {
- if (item.name.toLowerCase().indexOf(result[j].proc.toLowerCase()) >= 0) {
- listPos = j;
- }
- }
- // console.log(listPos);
- processes.forEach(function (proc) {
- // console.log(proc)
- // console.log(item)
- // inList = inList || item.name.toLowerCase() === proc.toLowerCase();
- if (item.name.toLowerCase().indexOf(proc.toLowerCase()) >= 0 && !inList) {
- inList = true;
- name = proc;
- }
- });
- // console.log(item);
- // console.log(listPos);
- if ((processesString === '*') || inList) {
- if (listPos < 0) {
- result.push({
- proc: name,
- pid: item.pid,
- pids: [item.pid],
- cpu: item.cpu,
- mem: item.mem
- });
- } else {
- result[listPos].pids.push(item.pid);
- result[listPos].cpu += item.cpu;
- result[listPos].mem += item.mem;
- }
- }
- });
- if (processesString !== '*') {
- // add missing processes
- let processesMissing = processes.filter(function (name) {
- return procStats.filter(function (item) { return item.name.toLowerCase().indexOf(name) >= 0; }).length === 0;
- });
- processesMissing.forEach(function (procName) {
- result.push({
- proc: procName,
- pid: null,
- pids: [],
- cpu: 0,
- mem: 0
- });
- });
- }
- if (_linux) {
- // calc process_cpu - ps is not accurate in linux!
- result.forEach(function (item) {
- item.cpu = 0;
- });
- let cmd = 'cat /proc/stat | grep "cpu "';
- for (let i in result) {
- for (let j in result[i].pids) {
- cmd += (';cat /proc/' + result[i].pids[j] + '/stat');
- }
- }
- exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
- let curr_processes = stdout.toString().split('\n');
- // first line (all - /proc/stat)
- let all = parseProcStat(curr_processes.shift());
- // process
- let list_new = {};
- let resultProcess = {};
- for (let i = 0; i < curr_processes.length; i++) {
- resultProcess = calcProcStatLinux(curr_processes[i], all, _process_cpu);
- if (resultProcess.pid) {
- // find result item
- let resultItemId = -1;
- for (let i in result) {
- if (result[i].pids.indexOf(resultProcess.pid) >= 0) {
- resultItemId = i;
- }
- }
- // store pcpu in outer result
- if (resultItemId >= 0) {
- result[resultItemId].cpu += resultProcess.cpuu + resultProcess.cpus;
- }
- // save new values
- list_new[resultProcess.pid] = {
- cpuu: resultProcess.cpuu,
- cpus: resultProcess.cpus,
- utime: resultProcess.utime,
- stime: resultProcess.stime,
- cutime: resultProcess.cutime,
- cstime: resultProcess.cstime
- };
- }
- }
- result.forEach(function (item) {
- item.cpu = Math.round(item.cpu * 100) / 100;
- });
- _process_cpu.all = all;
- // _process_cpu.list = list_new;
- _process_cpu.list = Object.assign({}, list_new);
- _process_cpu.ms = Date.now() - _process_cpu.ms;
- // _process_cpu.result = result;
- _process_cpu.result = Object.assign({}, result);
- if (callback) { callback(result); }
- resolve(result);
- });
- } else {
- if (callback) { callback(result); }
- resolve(result);
- }
- } else {
- if (callback) { callback(result); }
- resolve(result);
- }
- });
- }
- }
- });
- });
- }
- exports.processLoad = processLoad;
|