Repositorio del curso CCOM4030 el semestre B91 del proyecto Artesanías con el Instituto de Cultura

processes.js 39KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036
  1. 'use strict';
  2. // @ts-check
  3. // ==================================================================================
  4. // processes.js
  5. // ----------------------------------------------------------------------------------
  6. // Description: System Information - library
  7. // for Node.js
  8. // Copyright: (c) 2014 - 2020
  9. // Author: Sebastian Hildebrandt
  10. // ----------------------------------------------------------------------------------
  11. // License: MIT
  12. // ==================================================================================
  13. // 10. Processes
  14. // ----------------------------------------------------------------------------------
  15. const os = require('os');
  16. const fs = require('fs');
  17. const path = require('path');
  18. const exec = require('child_process').exec;
  19. const execSync = require('child_process').execSync;
  20. const util = require('./util');
  21. let _platform = process.platform;
  22. const _linux = (_platform === 'linux');
  23. const _darwin = (_platform === 'darwin');
  24. const _windows = (_platform === 'win32');
  25. const _freebsd = (_platform === 'freebsd');
  26. const _openbsd = (_platform === 'openbsd');
  27. const _netbsd = (_platform === 'netbsd');
  28. const _sunos = (_platform === 'sunos');
  29. const _processes_cpu = {
  30. all: 0,
  31. list: {},
  32. ms: 0,
  33. result: {}
  34. };
  35. const _services_cpu = {
  36. all: 0,
  37. list: {},
  38. ms: 0,
  39. result: {}
  40. };
  41. const _process_cpu = {
  42. all: 0,
  43. list: {},
  44. ms: 0,
  45. result: {}
  46. };
  47. const _winStatusValues = {
  48. '0': 'unknown',
  49. '1': 'other',
  50. '2': 'ready',
  51. '3': 'running',
  52. '4': 'blocked',
  53. '5': 'suspended blocked',
  54. '6': 'suspended ready',
  55. '7': 'terminated',
  56. '8': 'stopped',
  57. '9': 'growing',
  58. };
  59. function parseTimeWin(time) {
  60. time = time || '';
  61. if (time) {
  62. 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));
  63. } else {
  64. return '';
  65. }
  66. }
  67. function parseTimeUnix(time) {
  68. let result = time;
  69. let parts = time.replace(/ +/g, ' ').split(' ');
  70. if (parts.length === 5) {
  71. result = parts[4] + '-' + ('0' + ('JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC'.indexOf(parts[1].toUpperCase()) / 3 + 1)).slice(-2) + '-' + ('0' + parts[2]).slice(-2) + ' ' + parts[3];
  72. }
  73. return result;
  74. }
  75. // --------------------------
  76. // PS - services
  77. // pass a comma separated string with services to check (mysql, apache, postgresql, ...)
  78. // this function gives an array back, if the services are running.
  79. function services(srv, callback) {
  80. // fallback - if only callback is given
  81. if (util.isFunction(srv) && !callback) {
  82. callback = srv;
  83. srv = '';
  84. }
  85. return new Promise((resolve) => {
  86. process.nextTick(() => {
  87. if (srv) {
  88. let srvString = '';
  89. srvString.__proto__.toLowerCase = util.stringToLower;
  90. srvString.__proto__.replace = util.stringReplace;
  91. srvString.__proto__.trim = util.stringTrim;
  92. const s = util.sanitizeShellString(srv);
  93. for (let i = 0; i <= 2000; i++) {
  94. if (!(s[i] === undefined)) {
  95. srvString = srvString + s[i];
  96. }
  97. }
  98. srvString = srvString.trim().toLowerCase().replace(/, /g, '|').replace(/,+/g, '|');
  99. if (srvString === '') {
  100. srvString = '*';
  101. }
  102. if (util.isPrototypePolluted() && srvString !== '*') {
  103. srvString = '------';
  104. }
  105. let srvs = srvString.split('|');
  106. let result = [];
  107. let dataSrv = [];
  108. let allSrv = [];
  109. if (_linux || _freebsd || _openbsd || _netbsd || _darwin) {
  110. if ((_linux || _freebsd || _openbsd || _netbsd) && srvString === '*') {
  111. srvString = '';
  112. let tmpsrv = execSync('service --status-all 2> /dev/null').toString().split('\n');
  113. for (const s of tmpsrv) {
  114. const parts = s.split(']');
  115. if (parts.length === 2) {
  116. srvString += (srvString !== '' ? '|' : '') + parts[1].trim();
  117. allSrv.push({ name: parts[1].trim(), running: parts[0].indexOf('+') > 0 });
  118. }
  119. }
  120. srvs = srvString.split('|');
  121. }
  122. let comm = (_darwin) ? 'ps -caxo pcpu,pmem,pid,command' : 'ps -axo pcpu,pmem,pid,command';
  123. if (srvString !== '' && srvs.length > 0) {
  124. exec(comm + ' | grep -v grep | grep -iE "' + srvString + '"', { maxBuffer: 1024 * 20000 }, function (error, stdout) { // lgtm [js/shell-command-constructed-from-input]
  125. if (!error) {
  126. let lines = stdout.toString().replace(/ +/g, ' ').replace(/,+/g, '.').split('\n');
  127. srvs.forEach(function (srv) {
  128. let ps;
  129. if (_darwin) {
  130. ps = lines.filter(function (e) {
  131. return (e.toLowerCase().indexOf(srv) !== -1);
  132. });
  133. } else {
  134. ps = lines.filter(function (e) {
  135. return (e.toLowerCase().indexOf(' ' + srv + ':') !== -1) || (e.toLowerCase().indexOf('/' + srv) !== -1);
  136. });
  137. }
  138. let singleSrv = allSrv.filter(item => { return item.name === srv; });
  139. const pids = [];
  140. for (const p of ps) {
  141. const pid = p.trim().split(' ')[2];
  142. if (pid) {
  143. pids.push(parseInt(pid, 10));
  144. }
  145. }
  146. result.push({
  147. name: srv,
  148. running: (allSrv.length && singleSrv.length ? singleSrv[0].running : ps.length > 0),
  149. startmode: '',
  150. pids: pids,
  151. pcpu: parseFloat((ps.reduce(function (pv, cv) {
  152. return pv + parseFloat(cv.trim().split(' ')[0]);
  153. }, 0)).toFixed(2)),
  154. pmem: parseFloat((ps.reduce(function (pv, cv) {
  155. return pv + parseFloat(cv.trim().split(' ')[1]);
  156. }, 0)).toFixed(2))
  157. });
  158. });
  159. if (_linux) {
  160. // calc process_cpu - ps is not accurate in linux!
  161. let cmd = 'cat /proc/stat | grep "cpu "';
  162. for (let i in result) {
  163. for (let j in result[i].pids) {
  164. cmd += (';cat /proc/' + result[i].pids[j] + '/stat');
  165. }
  166. }
  167. exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
  168. let curr_processes = stdout.toString().split('\n');
  169. // first line (all - /proc/stat)
  170. let all = parseProcStat(curr_processes.shift());
  171. // process
  172. let list_new = {};
  173. let resultProcess = {};
  174. for (let i = 0; i < curr_processes.length; i++) {
  175. resultProcess = calcProcStatLinux(curr_processes[i], all, _services_cpu);
  176. if (resultProcess.pid) {
  177. let listPos = -1;
  178. for (let i in result) {
  179. for (let j in result[i].pids) {
  180. if (parseInt(result[i].pids[j]) === parseInt(resultProcess.pid)) {
  181. listPos = i;
  182. }
  183. }
  184. }
  185. if (listPos >= 0) {
  186. result[listPos].pcpu += resultProcess.pcpuu + resultProcess.pcpus;
  187. }
  188. // save new values
  189. list_new[resultProcess.pid] = {
  190. pcpuu: resultProcess.pcpuu,
  191. pcpus: resultProcess.pcpus,
  192. utime: resultProcess.utime,
  193. stime: resultProcess.stime,
  194. cutime: resultProcess.cutime,
  195. cstime: resultProcess.cstime
  196. };
  197. }
  198. }
  199. // store old values
  200. _services_cpu.all = all;
  201. // _services_cpu.list = list_new;
  202. _services_cpu.list = Object.assign({}, list_new);
  203. _services_cpu.ms = Date.now() - _services_cpu.ms;
  204. // _services_cpu.result = result;
  205. _services_cpu.result = Object.assign({}, result);
  206. if (callback) { callback(result); }
  207. resolve(result);
  208. });
  209. } else {
  210. if (callback) { callback(result); }
  211. resolve(result);
  212. }
  213. } else {
  214. exec('ps -o comm | grep -v grep | egrep "' + srvString + '"', { maxBuffer: 1024 * 20000 }, function (error, stdout) { // lgtm [js/shell-command-constructed-from-input]
  215. if (!error) {
  216. let lines = stdout.toString().replace(/ +/g, ' ').replace(/,+/g, '.').split('\n');
  217. srvs.forEach(function (srv) {
  218. let ps = lines.filter(function (e) {
  219. return e.indexOf(srv) !== -1;
  220. });
  221. result.push({
  222. name: srv,
  223. running: ps.length > 0,
  224. startmode: '',
  225. pcpu: 0,
  226. pmem: 0
  227. });
  228. });
  229. if (callback) { callback(result); }
  230. resolve(result);
  231. } else {
  232. srvs.forEach(function (srv) {
  233. result.push({
  234. name: srv,
  235. running: false,
  236. startmode: '',
  237. pcpu: 0,
  238. pmem: 0
  239. });
  240. });
  241. if (callback) { callback(result); }
  242. resolve(result);
  243. }
  244. });
  245. }
  246. });
  247. } else {
  248. if (callback) { callback(result); }
  249. resolve(result);
  250. }
  251. }
  252. if (_windows) {
  253. try {
  254. util.wmic('service get /value').then((stdout, error) => {
  255. if (!error) {
  256. let serviceSections = stdout.split(/\n\s*\n/);
  257. for (let i = 0; i < serviceSections.length; i++) {
  258. if (serviceSections[i].trim() !== '') {
  259. let lines = serviceSections[i].trim().split('\r\n');
  260. let srvName = util.getValue(lines, 'Name', '=', true).toLowerCase();
  261. let started = util.getValue(lines, 'Started', '=', true);
  262. let startMode = util.getValue(lines, 'StartMode', '=', true);
  263. let pid = util.getValue(lines, 'ProcessId', '=', true);
  264. if (srvString === '*' || srvs.indexOf(srvName) >= 0) {
  265. result.push({
  266. name: srvName,
  267. running: (started === 'TRUE'),
  268. startmode: startMode,
  269. pids: [pid],
  270. pcpu: 0,
  271. pmem: 0
  272. });
  273. dataSrv.push(srvName);
  274. }
  275. }
  276. }
  277. if (srvString !== '*') {
  278. let srvsMissing = srvs.filter(function (e) {
  279. return dataSrv.indexOf(e) === -1;
  280. });
  281. srvsMissing.forEach(function (srvName) {
  282. result.push({
  283. name: srvName,
  284. running: false,
  285. startmode: '',
  286. pids: [],
  287. pcpu: 0,
  288. pmem: 0
  289. });
  290. });
  291. }
  292. if (callback) { callback(result); }
  293. resolve(result);
  294. } else {
  295. srvs.forEach(function (srvName) {
  296. result.push({
  297. name: srvName,
  298. running: false,
  299. startmode: '',
  300. pcpu: 0,
  301. pmem: 0
  302. });
  303. });
  304. if (callback) { callback(result); }
  305. resolve(result);
  306. }
  307. });
  308. } catch (e) {
  309. if (callback) { callback(result); }
  310. resolve(result);
  311. }
  312. }
  313. } else {
  314. if (callback) { callback({}); }
  315. resolve({});
  316. }
  317. });
  318. });
  319. }
  320. exports.services = services;
  321. function parseProcStat(line) {
  322. let parts = line.replace(/ +/g, ' ').split(' ');
  323. let user = (parts.length >= 2 ? parseInt(parts[1]) : 0);
  324. let nice = (parts.length >= 3 ? parseInt(parts[2]) : 0);
  325. let system = (parts.length >= 4 ? parseInt(parts[3]) : 0);
  326. let idle = (parts.length >= 5 ? parseInt(parts[4]) : 0);
  327. let iowait = (parts.length >= 6 ? parseInt(parts[5]) : 0);
  328. let irq = (parts.length >= 7 ? parseInt(parts[6]) : 0);
  329. let softirq = (parts.length >= 8 ? parseInt(parts[7]) : 0);
  330. let steal = (parts.length >= 9 ? parseInt(parts[8]) : 0);
  331. let guest = (parts.length >= 10 ? parseInt(parts[9]) : 0);
  332. let guest_nice = (parts.length >= 11 ? parseInt(parts[10]) : 0);
  333. return user + nice + system + idle + iowait + irq + softirq + steal + guest + guest_nice;
  334. }
  335. function calcProcStatLinux(line, all, _cpu_old) {
  336. let statparts = line.replace(/ +/g, ' ').split(')');
  337. if (statparts.length >= 2) {
  338. let parts = statparts[1].split(' ');
  339. if (parts.length >= 16) {
  340. let pid = parseInt(statparts[0].split(' ')[0]);
  341. let utime = parseInt(parts[12]);
  342. let stime = parseInt(parts[13]);
  343. let cutime = parseInt(parts[14]);
  344. let cstime = parseInt(parts[15]);
  345. // calc
  346. let pcpuu = 0;
  347. let pcpus = 0;
  348. if (_cpu_old.all > 0 && _cpu_old.list[pid]) {
  349. pcpuu = (utime + cutime - _cpu_old.list[pid].utime - _cpu_old.list[pid].cutime) / (all - _cpu_old.all) * 100; // user
  350. pcpus = (stime + cstime - _cpu_old.list[pid].stime - _cpu_old.list[pid].cstime) / (all - _cpu_old.all) * 100; // system
  351. } else {
  352. pcpuu = (utime + cutime) / (all) * 100; // user
  353. pcpus = (stime + cstime) / (all) * 100; // system
  354. }
  355. return {
  356. pid: pid,
  357. utime: utime,
  358. stime: stime,
  359. cutime: cutime,
  360. cstime: cstime,
  361. pcpuu: pcpuu,
  362. pcpus: pcpus
  363. };
  364. } else {
  365. return {
  366. pid: 0,
  367. utime: 0,
  368. stime: 0,
  369. cutime: 0,
  370. cstime: 0,
  371. pcpuu: 0,
  372. pcpus: 0
  373. };
  374. }
  375. } else {
  376. return {
  377. pid: 0,
  378. utime: 0,
  379. stime: 0,
  380. cutime: 0,
  381. cstime: 0,
  382. pcpuu: 0,
  383. pcpus: 0
  384. };
  385. }
  386. }
  387. function calcProcStatWin(procStat, all, _cpu_old) {
  388. // calc
  389. let pcpuu = 0;
  390. let pcpus = 0;
  391. if (_cpu_old.all > 0 && _cpu_old.list[procStat.pid]) {
  392. pcpuu = (procStat.utime - _cpu_old.list[procStat.pid].utime) / (all - _cpu_old.all) * 100; // user
  393. pcpus = (procStat.stime - _cpu_old.list[procStat.pid].stime) / (all - _cpu_old.all) * 100; // system
  394. } else {
  395. pcpuu = (procStat.utime) / (all) * 100; // user
  396. pcpus = (procStat.stime) / (all) * 100; // system
  397. }
  398. return {
  399. pid: procStat.pid,
  400. utime: procStat.utime,
  401. stime: procStat.stime,
  402. pcpuu: pcpuu,
  403. pcpus: pcpus
  404. };
  405. }
  406. // --------------------------
  407. // running processes
  408. function processes(callback) {
  409. let parsedhead = [];
  410. function getName(command) {
  411. command = command || '';
  412. let result = command.split(' ')[0];
  413. if (result.substr(-1) === ':') {
  414. result = result.substr(0, result.length - 1);
  415. }
  416. if (result.substr(0, 1) !== '[') {
  417. let parts = result.split('/');
  418. if (isNaN(parseInt(parts[parts.length - 1]))) {
  419. result = parts[parts.length - 1];
  420. } else {
  421. result = parts[0];
  422. }
  423. }
  424. return result;
  425. }
  426. function parseLine(line) {
  427. let offset = 0;
  428. let offset2 = 0;
  429. function checkColumn(i) {
  430. offset = offset2;
  431. offset2 = line.substring(parsedhead[i].to + offset, 1000).indexOf(' ');
  432. }
  433. checkColumn(0);
  434. const pid = parseInt(line.substring(parsedhead[0].from + offset, parsedhead[0].to + offset2));
  435. checkColumn(1);
  436. const ppid = parseInt(line.substring(parsedhead[1].from + offset, parsedhead[1].to + offset2));
  437. checkColumn(2);
  438. const pcpu = parseFloat(line.substring(parsedhead[2].from + offset, parsedhead[2].to + offset2).replace(/,/g, '.'));
  439. checkColumn(3);
  440. const pmem = parseFloat(line.substring(parsedhead[3].from + offset, parsedhead[3].to + offset2).replace(/,/g, '.'));
  441. checkColumn(4);
  442. const priority = parseInt(line.substring(parsedhead[4].from + offset, parsedhead[4].to + offset2));
  443. checkColumn(5);
  444. const vsz = parseInt(line.substring(parsedhead[5].from + offset, parsedhead[5].to + offset2));
  445. checkColumn(6);
  446. const rss = parseInt(line.substring(parsedhead[6].from + offset, parsedhead[6].to + offset2));
  447. checkColumn(7);
  448. const nice = parseInt(line.substring(parsedhead[7].from + offset, parsedhead[7].to + offset2)) || 0;
  449. checkColumn(8);
  450. const started = parseTimeUnix(line.substring(parsedhead[8].from + offset, parsedhead[8].to + offset2).trim());
  451. checkColumn(9);
  452. let state = line.substring(parsedhead[9].from + offset, parsedhead[9].to + offset2).trim();
  453. 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')))))));
  454. checkColumn(10);
  455. let tty = line.substring(parsedhead[10].from + offset, parsedhead[10].to + offset2).trim();
  456. if (tty === '?' || tty === '??') tty = '';
  457. checkColumn(11);
  458. const user = line.substring(parsedhead[11].from + offset, parsedhead[11].to + offset2).trim();
  459. checkColumn(12);
  460. const fullcommand = line.substring(parsedhead[12].from + offset, parsedhead[12].to + offset2).trim().replace(/\[/g, '').replace(/]/g, '');
  461. let cmdPath = '';
  462. let command = '';
  463. let params = '';
  464. // try to figure out where parameter starts
  465. let firstParamPos = fullcommand.indexOf(' -');
  466. let firstParamPathPos = fullcommand.indexOf(' /');
  467. firstParamPos = (firstParamPos >= 0 ? firstParamPos : 10000);
  468. firstParamPathPos = (firstParamPathPos >= 0 ? firstParamPathPos : 10000);
  469. const firstPos = Math.min(firstParamPos, firstParamPathPos);
  470. let tmpCommand = fullcommand.substr(0, firstPos);
  471. const tmpParams = fullcommand.substr(firstPos);
  472. const lastSlashPos = tmpCommand.lastIndexOf('/');
  473. if (lastSlashPos >= 0) {
  474. cmdPath = tmpCommand.substr(0, lastSlashPos);
  475. tmpCommand = tmpCommand.substr(lastSlashPos + 1);
  476. }
  477. if (firstPos === 10000 && tmpCommand.indexOf(' ') > -1) {
  478. const parts = tmpCommand.split(' ');
  479. if (fs.existsSync(path.join(cmdPath, parts[0]))) {
  480. command = parts.shift();
  481. params = (parts.join(' ') + ' ' + tmpParams).trim();
  482. } else {
  483. command = tmpCommand.trim();
  484. params = tmpParams.trim();
  485. }
  486. } else {
  487. command = tmpCommand.trim();
  488. params = tmpParams.trim();
  489. }
  490. return ({
  491. pid: pid,
  492. parentPid: ppid,
  493. name: _linux ? getName(command) : command,
  494. pcpu: pcpu,
  495. pcpuu: 0,
  496. pcpus: 0,
  497. pmem: pmem,
  498. priority: priority,
  499. mem_vsz: vsz,
  500. mem_rss: rss,
  501. nice: nice,
  502. started: started,
  503. state: state,
  504. tty: tty,
  505. user: user,
  506. command: command,
  507. params: params,
  508. path: cmdPath
  509. });
  510. }
  511. function parseProcesses(lines) {
  512. let result = [];
  513. if (lines.length > 1) {
  514. let head = lines[0];
  515. parsedhead = util.parseHead(head, 8);
  516. lines.shift();
  517. lines.forEach(function (line) {
  518. if (line.trim() !== '') {
  519. result.push(parseLine(line));
  520. }
  521. });
  522. }
  523. return result;
  524. }
  525. function parseProcesses2(lines) {
  526. function formatDateTime(time) {
  527. const month = ('0' + (time.getMonth() + 1).toString()).substr(-2);
  528. const year = time.getFullYear().toString();
  529. const day = ('0' + time.getDay().toString()).substr(-2);
  530. const hours = time.getHours().toString();
  531. const mins = time.getMinutes().toString();
  532. const secs = ('0' + time.getSeconds().toString()).substr(-2);
  533. return (year + '-' + month + '-' + day + ' ' + hours + ':' + mins + ':' + secs);
  534. }
  535. let result = [];
  536. lines.forEach(function (line) {
  537. if (line.trim() !== '') {
  538. line = line.trim().replace(/ +/g, ' ').replace(/,+/g, '.');
  539. const parts = line.split(' ');
  540. const command = parts.slice(9).join(' ');
  541. const pmem = parseFloat((1.0 * parseInt(parts[3]) * 1024 / os.totalmem()).toFixed(1));
  542. const elapsed_parts = parts[5].split(':');
  543. const started = formatDateTime(new Date(Date.now() - (elapsed_parts.length > 1 ? (elapsed_parts[0] * 60 + elapsed_parts[1]) * 1000 : elapsed_parts[0] * 1000)));
  544. result.push({
  545. pid: parseInt(parts[0]),
  546. parentPid: parseInt(parts[1]),
  547. name: getName(command),
  548. pcpu: 0,
  549. pcpuu: 0,
  550. pcpus: 0,
  551. pmem: pmem,
  552. priority: 0,
  553. mem_vsz: parseInt(parts[2]),
  554. mem_rss: parseInt(parts[3]),
  555. nice: parseInt(parts[4]),
  556. started: started,
  557. 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'))))))),
  558. tty: parts[7],
  559. user: parts[8],
  560. command: command
  561. });
  562. }
  563. });
  564. return result;
  565. }
  566. return new Promise((resolve) => {
  567. process.nextTick(() => {
  568. let result = {
  569. all: 0,
  570. running: 0,
  571. blocked: 0,
  572. sleeping: 0,
  573. unknown: 0,
  574. list: []
  575. };
  576. let cmd = '';
  577. if ((_processes_cpu.ms && Date.now() - _processes_cpu.ms >= 500) || _processes_cpu.ms === 0) {
  578. if (_linux || _freebsd || _openbsd || _netbsd || _darwin || _sunos) {
  579. 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';
  580. 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';
  581. if (_darwin) cmd = 'export LC_ALL=C; ps -axo pid,ppid,pcpu,pmem,pri,vsz,rss,nice,lstart,state,tty,user,command -r; unset LC_ALL';
  582. if (_sunos) cmd = 'ps -Ao pid,ppid,pcpu,pmem,pri,vsz,rss,nice,stime,s,tty,user,comm';
  583. exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
  584. if (!error) {
  585. result.list = (parseProcesses(stdout.toString().split('\n'))).slice();
  586. result.all = result.list.length;
  587. result.running = result.list.filter(function (e) {
  588. return e.state === 'running';
  589. }).length;
  590. result.blocked = result.list.filter(function (e) {
  591. return e.state === 'blocked';
  592. }).length;
  593. result.sleeping = result.list.filter(function (e) {
  594. return e.state === 'sleeping';
  595. }).length;
  596. if (_linux) {
  597. // calc process_cpu - ps is not accurate in linux!
  598. cmd = 'cat /proc/stat | grep "cpu "';
  599. for (let i = 0; i < result.list.length; i++) {
  600. cmd += (';cat /proc/' + result.list[i].pid + '/stat');
  601. }
  602. exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
  603. let curr_processes = stdout.toString().split('\n');
  604. // first line (all - /proc/stat)
  605. let all = parseProcStat(curr_processes.shift());
  606. // process
  607. let list_new = {};
  608. let resultProcess = {};
  609. for (let i = 0; i < curr_processes.length; i++) {
  610. resultProcess = calcProcStatLinux(curr_processes[i], all, _processes_cpu);
  611. if (resultProcess.pid) {
  612. // store pcpu in outer array
  613. let listPos = result.list.map(function (e) { return e.pid; }).indexOf(resultProcess.pid);
  614. if (listPos >= 0) {
  615. result.list[listPos].pcpu = resultProcess.pcpuu + resultProcess.pcpus;
  616. result.list[listPos].pcpuu = resultProcess.pcpuu;
  617. result.list[listPos].pcpus = resultProcess.pcpus;
  618. }
  619. // save new values
  620. list_new[resultProcess.pid] = {
  621. pcpuu: resultProcess.pcpuu,
  622. pcpus: resultProcess.pcpus,
  623. utime: resultProcess.utime,
  624. stime: resultProcess.stime,
  625. cutime: resultProcess.cutime,
  626. cstime: resultProcess.cstime
  627. };
  628. }
  629. }
  630. // store old values
  631. _processes_cpu.all = all;
  632. // _processes_cpu.list = list_new;
  633. _processes_cpu.list = Object.assign({}, list_new);
  634. _processes_cpu.ms = Date.now() - _processes_cpu.ms;
  635. // _processes_cpu.result = result;
  636. _processes_cpu.result = Object.assign({}, result);
  637. if (callback) { callback(result); }
  638. resolve(result);
  639. });
  640. } else {
  641. if (callback) { callback(result); }
  642. resolve(result);
  643. }
  644. } else {
  645. cmd = 'ps -o pid,ppid,vsz,rss,nice,etime,stat,tty,user,comm';
  646. if (_sunos) {
  647. cmd = 'ps -o pid,ppid,vsz,rss,nice,etime,s,tty,user,comm';
  648. }
  649. exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
  650. if (!error) {
  651. let lines = stdout.toString().split('\n');
  652. lines.shift();
  653. result.list = parseProcesses2(lines).slice();
  654. result.all = result.list.length;
  655. result.running = result.list.filter(function (e) {
  656. return e.state === 'running';
  657. }).length;
  658. result.blocked = result.list.filter(function (e) {
  659. return e.state === 'blocked';
  660. }).length;
  661. result.sleeping = result.list.filter(function (e) {
  662. return e.state === 'sleeping';
  663. }).length;
  664. if (callback) { callback(result); }
  665. resolve(result);
  666. } else {
  667. if (callback) { callback(result); }
  668. resolve(result);
  669. }
  670. });
  671. }
  672. });
  673. } else if (_windows) {
  674. try {
  675. util.wmic('process get /value').then((stdout, error) => {
  676. if (!error) {
  677. let processSections = stdout.split(/\n\s*\n/);
  678. let procs = [];
  679. let procStats = [];
  680. let list_new = {};
  681. let allcpuu = 0;
  682. let allcpus = 0;
  683. for (let i = 0; i < processSections.length; i++) {
  684. if (processSections[i].trim() !== '') {
  685. let lines = processSections[i].trim().split('\r\n');
  686. let pid = parseInt(util.getValue(lines, 'ProcessId', '=', true), 10);
  687. let parentPid = parseInt(util.getValue(lines, 'ParentProcessId', '=', true), 10);
  688. let statusValue = util.getValue(lines, 'ExecutionState', '=');
  689. let name = util.getValue(lines, 'Caption', '=', true);
  690. let commandLine = util.getValue(lines, 'CommandLine', '=', true);
  691. let commandPath = util.getValue(lines, 'ExecutablePath', '=', true);
  692. let utime = parseInt(util.getValue(lines, 'UserModeTime', '=', true), 10);
  693. let stime = parseInt(util.getValue(lines, 'KernelModeTime', '=', true), 10);
  694. let mem = parseInt(util.getValue(lines, 'WorkingSetSize', '=', true), 10);
  695. allcpuu = allcpuu + utime;
  696. allcpus = allcpus + stime;
  697. result.all++;
  698. if (!statusValue) { result.unknown++; }
  699. if (statusValue === '3') { result.running++; }
  700. if (statusValue === '4' || statusValue === '5') { result.blocked++; }
  701. procStats.push({
  702. pid: pid,
  703. utime: utime,
  704. stime: stime,
  705. pcpu: 0,
  706. pcpuu: 0,
  707. pcpus: 0,
  708. });
  709. procs.push({
  710. pid: pid,
  711. parentPid: parentPid,
  712. name: name,
  713. pcpu: 0,
  714. pcpuu: 0,
  715. pcpus: 0,
  716. pmem: mem / os.totalmem() * 100,
  717. priority: parseInt(util.getValue(lines, 'Priority', '=', true), 10),
  718. mem_vsz: parseInt(util.getValue(lines, 'PageFileUsage', '=', true), 10),
  719. mem_rss: Math.floor(parseInt(util.getValue(lines, 'WorkingSetSize', '=', true), 10) / 1024),
  720. nice: 0,
  721. started: parseTimeWin(util.getValue(lines, 'CreationDate', '=', true)),
  722. state: (!statusValue ? _winStatusValues[0] : _winStatusValues[statusValue]),
  723. tty: '',
  724. user: '',
  725. command: commandLine || name,
  726. path: commandPath,
  727. params: ''
  728. });
  729. }
  730. }
  731. result.sleeping = result.all - result.running - result.blocked - result.unknown;
  732. result.list = procs;
  733. for (let i = 0; i < procStats.length; i++) {
  734. let resultProcess = calcProcStatWin(procStats[i], allcpuu + allcpus, _processes_cpu);
  735. // store pcpu in outer array
  736. let listPos = result.list.map(function (e) { return e.pid; }).indexOf(resultProcess.pid);
  737. if (listPos >= 0) {
  738. result.list[listPos].pcpu = resultProcess.pcpuu + resultProcess.pcpus;
  739. result.list[listPos].pcpuu = resultProcess.pcpuu;
  740. result.list[listPos].pcpus = resultProcess.pcpus;
  741. }
  742. // save new values
  743. list_new[resultProcess.pid] = {
  744. pcpuu: resultProcess.pcpuu,
  745. pcpus: resultProcess.pcpus,
  746. utime: resultProcess.utime,
  747. stime: resultProcess.stime
  748. };
  749. }
  750. // store old values
  751. _processes_cpu.all = allcpuu + allcpus;
  752. // _processes_cpu.list = list_new;
  753. _processes_cpu.list = Object.assign({}, list_new);
  754. _processes_cpu.ms = Date.now() - _processes_cpu.ms;
  755. // _processes_cpu.result = result;
  756. _processes_cpu.result = Object.assign({}, result);
  757. }
  758. if (callback) {
  759. callback(result);
  760. }
  761. resolve(result);
  762. });
  763. } catch (e) {
  764. if (callback) { callback(result); }
  765. resolve(result);
  766. }
  767. } else {
  768. if (callback) { callback(result); }
  769. resolve(result);
  770. }
  771. } else {
  772. if (callback) { callback(_processes_cpu.result); }
  773. resolve(_processes_cpu.result);
  774. }
  775. });
  776. });
  777. }
  778. exports.processes = processes;
  779. // --------------------------
  780. // PS - process load
  781. // get detailed information about a certain process
  782. // (PID, CPU-Usage %, Mem-Usage %)
  783. function processLoad(proc, callback) {
  784. // fallback - if only callback is given
  785. if (util.isFunction(proc) && !callback) {
  786. callback = proc;
  787. proc = '';
  788. }
  789. return new Promise((resolve) => {
  790. process.nextTick(() => {
  791. const procSanitized = util.isPrototypePolluted() ? '' : util.sanitizeShellString(proc);
  792. let result = {
  793. 'proc': procSanitized,
  794. 'pid': -1,
  795. 'cpu': 0,
  796. 'mem': 0
  797. };
  798. if (procSanitized) {
  799. if (_windows) {
  800. try {
  801. util.wmic('process get /value').then((stdout, error) => {
  802. if (!error) {
  803. let processSections = stdout.split(/\n\s*\n/);
  804. let procStats = [];
  805. let list_new = {};
  806. let allcpuu = 0;
  807. let allcpus = 0;
  808. for (let i = 0; i < processSections.length; i++) {
  809. if (processSections[i].trim() !== '') {
  810. let lines = processSections[i].trim().split('\r\n');
  811. let pid = parseInt(util.getValue(lines, 'ProcessId', '=', true), 10);
  812. let name = util.getValue(lines, 'Caption', '=', true);
  813. let utime = parseInt(util.getValue(lines, 'UserModeTime', '=', true), 10);
  814. let stime = parseInt(util.getValue(lines, 'KernelModeTime', '=', true), 10);
  815. let mem = parseInt(util.getValue(lines, 'WorkingSetSize', '=', true), 10);
  816. allcpuu = allcpuu + utime;
  817. allcpus = allcpus + stime;
  818. procStats.push({
  819. pid: pid,
  820. utime: utime,
  821. stime: stime,
  822. pcpu: 0,
  823. pcpuu: 0,
  824. pcpus: 0,
  825. });
  826. if (name.toLowerCase().indexOf(procSanitized.toLowerCase()) >= 0) {
  827. if (result.pid === -1) {
  828. result = {
  829. proc: name,
  830. pid: pid,
  831. pids: [pid],
  832. cpu: 0,
  833. mem: mem / os.totalmem() * 100
  834. };
  835. } else {
  836. result.pids.push(pid);
  837. result.mem += mem / os.totalmem() * 100;
  838. }
  839. }
  840. }
  841. }
  842. for (let i = 0; i < procStats.length; i++) {
  843. let resultProcess = calcProcStatWin(procStats[i], allcpuu + allcpus, _process_cpu);
  844. // store pcpu in outer array
  845. if (result && result.pids && result.pids.length > 0) {
  846. let listPos = result.pids.indexOf(resultProcess.pid);
  847. if (listPos >= 0) {
  848. result.cpu = resultProcess.pcpuu + resultProcess.pcpus;
  849. }
  850. }
  851. // save new values
  852. list_new[resultProcess.pid] = {
  853. pcpuu: resultProcess.pcpuu,
  854. pcpus: resultProcess.pcpus,
  855. utime: resultProcess.utime,
  856. stime: resultProcess.stime
  857. };
  858. }
  859. // store old values
  860. _process_cpu.all = allcpuu + allcpus;
  861. // _process_cpu.list = list_new;
  862. _process_cpu.list = Object.assign({}, list_new);
  863. _process_cpu.ms = Date.now() - _process_cpu.ms;
  864. // _process_cpu.result = result;
  865. _process_cpu.result = Object.assign({}, result);
  866. if (callback) {
  867. callback(result);
  868. }
  869. resolve(result);
  870. }
  871. });
  872. } catch (e) {
  873. if (callback) { callback(result); }
  874. resolve(result);
  875. }
  876. }
  877. if (_darwin || _linux) {
  878. exec('ps -axo pid,pcpu,pmem,comm | grep -i ' + procSanitized + ' | grep -v grep', { maxBuffer: 1024 * 20000 }, function (error, stdout) {
  879. if (!error) {
  880. let lines = stdout.toString().split('\n');
  881. let pid = 0;
  882. let pids = [];
  883. let cpu = 0;
  884. let mem = 0;
  885. lines.forEach(function (line) {
  886. let data = line.trim().replace(/ +/g, ' ').split(' ');
  887. if (data.length > 3) {
  888. pid = (!pid ? parseInt(data[0]) : 0);
  889. pids.push(parseInt(data[0], 10));
  890. cpu = cpu + parseFloat(data[1].replace(',', '.'));
  891. mem = mem + parseFloat(data[2].replace(',', '.'));
  892. }
  893. });
  894. result = {
  895. 'proc': procSanitized,
  896. 'pid': pid,
  897. 'pids': pids,
  898. 'cpu': parseFloat((cpu / lines.length).toFixed(2)),
  899. 'mem': parseFloat((mem / lines.length).toFixed(2))
  900. };
  901. if (_linux) {
  902. // calc process_cpu - ps is not accurate in linux!
  903. let cmd = 'cat /proc/stat | grep "cpu "';
  904. for (let i = 0; i < result.pids.length; i++) {
  905. cmd += (';cat /proc/' + result.pids[i] + '/stat');
  906. }
  907. exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
  908. let curr_processes = stdout.toString().split('\n');
  909. // first line (all - /proc/stat)
  910. let all = parseProcStat(curr_processes.shift());
  911. // process
  912. let list_new = {};
  913. let resultProcess = {};
  914. result.cpu = 0;
  915. for (let i = 0; i < curr_processes.length; i++) {
  916. resultProcess = calcProcStatLinux(curr_processes[i], all, _process_cpu);
  917. if (resultProcess.pid) {
  918. // store pcpu in outer result
  919. result.cpu += resultProcess.pcpuu + resultProcess.pcpus;
  920. // save new values
  921. list_new[resultProcess.pid] = {
  922. pcpuu: resultProcess.pcpuu,
  923. pcpus: resultProcess.pcpus,
  924. utime: resultProcess.utime,
  925. stime: resultProcess.stime,
  926. cutime: resultProcess.cutime,
  927. cstime: resultProcess.cstime
  928. };
  929. }
  930. }
  931. result.cpu = Math.round(result.cpu * 100) / 100;
  932. _process_cpu.all = all;
  933. // _process_cpu.list = list_new;
  934. _process_cpu.list = Object.assign({}, list_new);
  935. _process_cpu.ms = Date.now() - _process_cpu.ms;
  936. // _process_cpu.result = result;
  937. _process_cpu.result = Object.assign({}, result);
  938. if (callback) { callback(result); }
  939. resolve(result);
  940. });
  941. } else {
  942. if (callback) { callback(result); }
  943. resolve(result);
  944. }
  945. } else {
  946. if (callback) { callback(result); }
  947. resolve(result);
  948. }
  949. });
  950. }
  951. }
  952. });
  953. });
  954. }
  955. exports.processLoad = processLoad;