diff options
author | Minteck <contact@minteck.org> | 2022-07-05 13:40:01 +0200 |
---|---|---|
committer | Minteck <contact@minteck.org> | 2022-07-05 13:40:01 +0200 |
commit | b74e9708f0adcc5c80095e432e8051b01b6255d9 (patch) | |
tree | e4d2fec7ac3718f97966b10f7dc12a2b4d36d115 /node_modules/systeminformation/lib/processes.js | |
download | strawberry-boot-b74e9708f0adcc5c80095e432e8051b01b6255d9.tar.gz strawberry-boot-b74e9708f0adcc5c80095e432e8051b01b6255d9.tar.bz2 strawberry-boot-b74e9708f0adcc5c80095e432e8051b01b6255d9.zip |
Diffstat (limited to 'node_modules/systeminformation/lib/processes.js')
-rw-r--r-- | node_modules/systeminformation/lib/processes.js | 1291 |
1 files changed, 1291 insertions, 0 deletions
diff --git a/node_modules/systeminformation/lib/processes.js b/node_modules/systeminformation/lib/processes.js new file mode 100644 index 0000000..f49d7de --- /dev/null +++ b/node_modules/systeminformation/lib/processes.js @@ -0,0 +1,1291 @@ +'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; +} + +function parseElapsedTime(etime) { + let current = new Date(); + current = new Date(current.getTime() - current.getTimezoneOffset() * 60000); + + const elapsed = etime.split('-'); + + const timeIndex = elapsed.length - 1; + const days = timeIndex > 0 ? parseInt(elapsed[timeIndex - 1]) : 0; + + const timeStr = elapsed[timeIndex].split(':'); + const hours = timeStr.length === 3 ? parseInt(timeStr[0] || 0) : 0; + const mins = parseInt(timeStr[timeStr.length === 3 ? 1 : 0] || 0); + const secs = parseInt(timeStr[timeStr.length === 3 ? 2 : 1] || 0); + const ms = (((((days * 24 + hours) * 60) + mins) * 60 + secs) * 1000); + + const res = new Date(current.getTime() - ms); + return res.toISOString().substring(0, 10) + ' ' + res.toISOString().substring(11, 19); +} + +// -------------------------- +// 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 = !_sunos ? parseElapsedTime(line.substring(parsedhead[8].from + offset, parsedhead[8].to + offset2).trim()) : 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 { + const p1 = fullcommand.indexOf('('); + const p2 = fullcommand.indexOf(')'); + const p3 = fullcommand.indexOf('/'); + const p4 = fullcommand.indexOf(':'); + if (p1 < p2 && p1 < p3 && p3 < p2) { + command = fullcommand.split(' ')[0]; + command = command.replace(/:/g, ''); + } else { + if (p4 > 0 && (p3 === -1 || p3 > 3)) { + command = fullcommand.split(' ')[0]; + command = command.replace(/:/g, ''); + } 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,etime: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,etime,state,tty,user,command; unset LC_ALL'; } + if (_darwin) { cmd = 'ps -axo pid,ppid,pcpu,pmem,pri,vsz=temp_title_1,rss=temp_title_2,nice,etime=temp_title_3,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; |