sysiddr5 1.0.1-beta-3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of sysiddr5 might be problematic. Click here for more details.

@@ -0,0 +1,1289 @@
1
+ 'use strict';
2
+ // @ts-check
3
+ // ==================================================================================
4
+ // processes.js
5
+ // ----------------------------------------------------------------------------------
6
+ // Description: System Information - library
7
+ // for Node.js
8
+ // Copyright: (c) 2014 - 2023
9
+ // Author: Sebastian Hildebrandt
10
+ // ----------------------------------------------------------------------------------
11
+ // License: MIT
12
+ // ==================================================================================
13
+ // 10. Processes
14
+ // ----------------------------------------------------------------------------------
15
+
16
+ const os = require('os');
17
+ const fs = require('fs');
18
+ const path = require('path');
19
+ const exec = require('child_process').exec;
20
+ const execSync = require('child_process').execSync;
21
+
22
+ const util = require('./util');
23
+
24
+ let _platform = process.platform;
25
+
26
+ const _linux = (_platform === 'linux' || _platform === 'android');
27
+ const _darwin = (_platform === 'darwin');
28
+ const _windows = (_platform === 'win32');
29
+ const _freebsd = (_platform === 'freebsd');
30
+ const _openbsd = (_platform === 'openbsd');
31
+ const _netbsd = (_platform === 'netbsd');
32
+ const _sunos = (_platform === 'sunos');
33
+
34
+ const _processes_cpu = {
35
+ all: 0,
36
+ all_utime: 0,
37
+ all_stime: 0,
38
+ list: {},
39
+ ms: 0,
40
+ result: {}
41
+ };
42
+ const _services_cpu = {
43
+ all: 0,
44
+ all_utime: 0,
45
+ all_stime: 0,
46
+ list: {},
47
+ ms: 0,
48
+ result: {}
49
+ };
50
+ const _process_cpu = {
51
+ all: 0,
52
+ all_utime: 0,
53
+ all_stime: 0,
54
+ list: {},
55
+ ms: 0,
56
+ result: {}
57
+ };
58
+
59
+ const _winStatusValues = {
60
+ '0': 'unknown',
61
+ '1': 'other',
62
+ '2': 'ready',
63
+ '3': 'running',
64
+ '4': 'blocked',
65
+ '5': 'suspended blocked',
66
+ '6': 'suspended ready',
67
+ '7': 'terminated',
68
+ '8': 'stopped',
69
+ '9': 'growing',
70
+ };
71
+
72
+ function parseTimeUnix(time) {
73
+ let result = time;
74
+ let parts = time.replace(/ +/g, ' ').split(' ');
75
+ if (parts.length === 5) {
76
+ result = parts[4] + '-' + ('0' + ('JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC'.indexOf(parts[1].toUpperCase()) / 3 + 1)).slice(-2) + '-' + ('0' + parts[2]).slice(-2) + ' ' + parts[3];
77
+ }
78
+ return result;
79
+ }
80
+
81
+ function parseElapsedTime(etime) {
82
+ let current = new Date();
83
+ current = new Date(current.getTime() - current.getTimezoneOffset() * 60000);
84
+
85
+ const elapsed = etime.split('-');
86
+
87
+ const timeIndex = elapsed.length - 1;
88
+ const days = timeIndex > 0 ? parseInt(elapsed[timeIndex - 1]) : 0;
89
+
90
+ const timeStr = elapsed[timeIndex].split(':');
91
+ const hours = timeStr.length === 3 ? parseInt(timeStr[0] || 0) : 0;
92
+ const mins = parseInt(timeStr[timeStr.length === 3 ? 1 : 0] || 0);
93
+ const secs = parseInt(timeStr[timeStr.length === 3 ? 2 : 1] || 0);
94
+ const ms = (((((days * 24 + hours) * 60) + mins) * 60 + secs) * 1000);
95
+
96
+ let res = new Date(current.getTime());
97
+ let result = res.toISOString().substring(0, 10) + ' ' + res.toISOString().substring(11, 19);
98
+ try {
99
+ res = new Date(current.getTime() - ms);
100
+ result = res.toISOString().substring(0, 10) + ' ' + res.toISOString().substring(11, 19);
101
+ } catch (e) {
102
+ util.noop();
103
+ }
104
+ return result;
105
+ }
106
+
107
+ // --------------------------
108
+ // PS - services
109
+ // pass a comma separated string with services to check (mysql, apache, postgresql, ...)
110
+ // this function gives an array back, if the services are running.
111
+
112
+ function services(srv, callback) {
113
+
114
+ // fallback - if only callback is given
115
+ if (util.isFunction(srv) && !callback) {
116
+ callback = srv;
117
+ srv = '';
118
+ }
119
+
120
+ return new Promise((resolve) => {
121
+ process.nextTick(() => {
122
+ if (typeof srv !== 'string') {
123
+ if (callback) { callback([]); }
124
+ return resolve([]);
125
+ }
126
+
127
+ if (srv) {
128
+ let srvString = '';
129
+ srvString.__proto__.toLowerCase = util.stringToLower;
130
+ srvString.__proto__.replace = util.stringReplace;
131
+ srvString.__proto__.trim = util.stringTrim;
132
+
133
+ const s = util.sanitizeShellString(srv);
134
+ for (let i = 0; i <= util.mathMin(s.length, 2000); i++) {
135
+ if (s[i] !== undefined) {
136
+ srvString = srvString + s[i];
137
+ }
138
+ }
139
+
140
+ srvString = srvString.trim().toLowerCase().replace(/, /g, '|').replace(/,+/g, '|');
141
+ if (srvString === '') {
142
+ srvString = '*';
143
+ }
144
+ if (util.isPrototypePolluted() && srvString !== '*') {
145
+ srvString = '------';
146
+ }
147
+ let srvs = srvString.split('|');
148
+ let result = [];
149
+ let dataSrv = [];
150
+
151
+ if (_linux || _freebsd || _openbsd || _netbsd || _darwin) {
152
+ if ((_linux || _freebsd || _openbsd || _netbsd) && srvString === '*') {
153
+ try {
154
+ const tmpsrv = execSync('systemctl --all --type=service --no-legend 2> /dev/null').toString().split('\n');
155
+ srvs = [];
156
+ for (const s of tmpsrv) {
157
+ const name = s.split('.service')[0];
158
+ if (name && s.indexOf(' not-found ') === -1) {
159
+ srvs.push(name.trim());
160
+ }
161
+ }
162
+ srvString = srvs.join('|');
163
+ } catch (d) {
164
+ try {
165
+ srvString = '';
166
+ const tmpsrv = execSync('service --status-all 2> /dev/null').toString().split('\n');
167
+ for (const s of tmpsrv) {
168
+ const parts = s.split(']');
169
+ if (parts.length === 2) {
170
+ srvString += (srvString !== '' ? '|' : '') + parts[1].trim();
171
+ }
172
+ }
173
+ srvs = srvString.split('|');
174
+ } catch (e) {
175
+ try {
176
+ const srvStr = execSync('ls /etc/init.d/ -m 2> /dev/null').toString().split('\n').join('');
177
+ srvString = '';
178
+ if (srvStr) {
179
+ const tmpsrv = srvStr.split(',');
180
+ for (const s of tmpsrv) {
181
+ const name = s.trim();
182
+ if (name) {
183
+ srvString += (srvString !== '' ? '|' : '') + name;
184
+ }
185
+ }
186
+ srvs = srvString.split('|');
187
+ }
188
+ } catch (f) {
189
+ srvString = '';
190
+ srvs = [];
191
+ }
192
+ }
193
+ }
194
+ }
195
+ if ((_darwin) && srvString === '*') { // service enumeration not yet suported on mac OS
196
+ if (callback) { callback(result); }
197
+ resolve(result);
198
+ }
199
+ let args = (_darwin) ? ['-caxo', 'pcpu,pmem,pid,command'] : ['-axo', 'pcpu,pmem,pid,command'];
200
+ if (srvString !== '' && srvs.length > 0) {
201
+ util.execSafe('ps', args).then((stdout) => {
202
+ if (stdout) {
203
+ let lines = stdout.replace(/ +/g, ' ').replace(/,+/g, '.').split('\n');
204
+ srvs.forEach(function (srv) {
205
+ let ps;
206
+ if (_darwin) {
207
+ ps = lines.filter(function (e) {
208
+ return (e.toLowerCase().indexOf(srv) !== -1);
209
+ });
210
+
211
+ } else {
212
+ ps = lines.filter(function (e) {
213
+ return (e.toLowerCase().indexOf(' ' + srv + ':') !== -1) || (e.toLowerCase().indexOf('/' + srv) !== -1);
214
+ });
215
+ }
216
+ const pids = [];
217
+ for (const p of ps) {
218
+ const pid = p.trim().split(' ')[2];
219
+ if (pid) {
220
+ pids.push(parseInt(pid, 10));
221
+ }
222
+ }
223
+ result.push({
224
+ name: srv,
225
+ running: ps.length > 0,
226
+ startmode: '',
227
+ pids: pids,
228
+ cpu: parseFloat((ps.reduce(function (pv, cv) {
229
+ return pv + parseFloat(cv.trim().split(' ')[0]);
230
+ }, 0)).toFixed(2)),
231
+ mem: parseFloat((ps.reduce(function (pv, cv) {
232
+ return pv + parseFloat(cv.trim().split(' ')[1]);
233
+ }, 0)).toFixed(2))
234
+ });
235
+ });
236
+ if (_linux) {
237
+ // calc process_cpu - ps is not accurate in linux!
238
+ let cmd = 'cat /proc/stat | grep "cpu "';
239
+ for (let i in result) {
240
+ for (let j in result[i].pids) {
241
+ cmd += (';cat /proc/' + result[i].pids[j] + '/stat');
242
+ }
243
+ }
244
+ exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
245
+ let curr_processes = stdout.toString().split('\n');
246
+
247
+ // first line (all - /proc/stat)
248
+ let all = parseProcStat(curr_processes.shift());
249
+
250
+ // process
251
+ let list_new = {};
252
+ let resultProcess = {};
253
+ curr_processes.forEach((element) => {
254
+ resultProcess = calcProcStatLinux(element, all, _services_cpu);
255
+
256
+ if (resultProcess.pid) {
257
+ let listPos = -1;
258
+ for (let i in result) {
259
+ for (let j in result[i].pids) {
260
+ if (parseInt(result[i].pids[j]) === parseInt(resultProcess.pid)) {
261
+ listPos = i;
262
+ }
263
+ }
264
+ }
265
+ if (listPos >= 0) {
266
+ result[listPos].cpu += resultProcess.cpuu + resultProcess.cpus;
267
+ }
268
+
269
+ // save new values
270
+ list_new[resultProcess.pid] = {
271
+ cpuu: resultProcess.cpuu,
272
+ cpus: resultProcess.cpus,
273
+ utime: resultProcess.utime,
274
+ stime: resultProcess.stime,
275
+ cutime: resultProcess.cutime,
276
+ cstime: resultProcess.cstime
277
+ };
278
+ }
279
+ });
280
+
281
+ // store old values
282
+ _services_cpu.all = all;
283
+ _services_cpu.list = Object.assign({}, list_new);
284
+ _services_cpu.ms = Date.now() - _services_cpu.ms;
285
+ _services_cpu.result = Object.assign({}, result);
286
+ if (callback) { callback(result); }
287
+ resolve(result);
288
+ });
289
+ } else {
290
+ if (callback) { callback(result); }
291
+ resolve(result);
292
+ }
293
+ } else {
294
+ args = ['-o', 'comm'];
295
+ util.execSafe('ps', args).then((stdout) => {
296
+ if (stdout) {
297
+ let lines = stdout.replace(/ +/g, ' ').replace(/,+/g, '.').split('\n');
298
+ srvs.forEach(function (srv) {
299
+ let ps = lines.filter(function (e) {
300
+ return e.indexOf(srv) !== -1;
301
+ });
302
+ result.push({
303
+ name: srv,
304
+ running: ps.length > 0,
305
+ startmode: '',
306
+ cpu: 0,
307
+ mem: 0
308
+ });
309
+ });
310
+ if (callback) { callback(result); }
311
+ resolve(result);
312
+ } else {
313
+ srvs.forEach(function (srv) {
314
+ result.push({
315
+ name: srv,
316
+ running: false,
317
+ startmode: '',
318
+ cpu: 0,
319
+ mem: 0
320
+ });
321
+ });
322
+ if (callback) { callback(result); }
323
+ resolve(result);
324
+ }
325
+ });
326
+ }
327
+ });
328
+ } else {
329
+ if (callback) { callback(result); }
330
+ resolve(result);
331
+ }
332
+ }
333
+ if (_windows) {
334
+ try {
335
+ let wincommand = 'Get-CimInstance Win32_Service';
336
+ if (srvs[0] !== '*') {
337
+ wincommand += ' -Filter "';
338
+ srvs.forEach((srv) => {
339
+ wincommand += `Name='${srv}' or `;
340
+ });
341
+ wincommand = `${wincommand.slice(0, -4)}"`;
342
+ }
343
+ wincommand += ' | select Name,Caption,Started,StartMode,ProcessId | fl';
344
+ util.powerShell(wincommand).then((stdout, error) => {
345
+ if (!error) {
346
+ let serviceSections = stdout.split(/\n\s*\n/);
347
+ serviceSections.forEach((element) => {
348
+ if (element.trim() !== '') {
349
+ let lines = element.trim().split('\r\n');
350
+ let srvName = util.getValue(lines, 'Name', ':', true).toLowerCase();
351
+ let srvCaption = util.getValue(lines, 'Caption', ':', true).toLowerCase();
352
+ let started = util.getValue(lines, 'Started', ':', true);
353
+ let startMode = util.getValue(lines, 'StartMode', ':', true);
354
+ let pid = util.getValue(lines, 'ProcessId', ':', true);
355
+ if (srvString === '*' || srvs.indexOf(srvName) >= 0 || srvs.indexOf(srvCaption) >= 0) {
356
+ result.push({
357
+ name: srvName,
358
+ running: (started.toLowerCase() === 'true'),
359
+ startmode: startMode,
360
+ pids: [pid],
361
+ cpu: 0,
362
+ mem: 0
363
+ });
364
+ dataSrv.push(srvName);
365
+ dataSrv.push(srvCaption);
366
+ }
367
+ }
368
+
369
+ });
370
+
371
+ if (srvString !== '*') {
372
+ let srvsMissing = srvs.filter(function (e) {
373
+ return dataSrv.indexOf(e) === -1;
374
+ });
375
+ srvsMissing.forEach(function (srvName) {
376
+ result.push({
377
+ name: srvName,
378
+ running: false,
379
+ startmode: '',
380
+ pids: [],
381
+ cpu: 0,
382
+ mem: 0
383
+ });
384
+ });
385
+ }
386
+ if (callback) { callback(result); }
387
+ resolve(result);
388
+ } else {
389
+ srvs.forEach(function (srvName) {
390
+ result.push({
391
+ name: srvName,
392
+ running: false,
393
+ startmode: '',
394
+ cpu: 0,
395
+ mem: 0
396
+ });
397
+ });
398
+ if (callback) { callback(result); }
399
+ resolve(result);
400
+ }
401
+ });
402
+ } catch (e) {
403
+ if (callback) { callback(result); }
404
+ resolve(result);
405
+ }
406
+ }
407
+ } else {
408
+ if (callback) { callback([]); }
409
+ resolve([]);
410
+ }
411
+ });
412
+ });
413
+ }
414
+
415
+ exports.services = services;
416
+
417
+ function parseProcStat(line) {
418
+ let parts = line.replace(/ +/g, ' ').split(' ');
419
+ let user = (parts.length >= 2 ? parseInt(parts[1]) : 0);
420
+ let nice = (parts.length >= 3 ? parseInt(parts[2]) : 0);
421
+ let system = (parts.length >= 4 ? parseInt(parts[3]) : 0);
422
+ let idle = (parts.length >= 5 ? parseInt(parts[4]) : 0);
423
+ let iowait = (parts.length >= 6 ? parseInt(parts[5]) : 0);
424
+ let irq = (parts.length >= 7 ? parseInt(parts[6]) : 0);
425
+ let softirq = (parts.length >= 8 ? parseInt(parts[7]) : 0);
426
+ let steal = (parts.length >= 9 ? parseInt(parts[8]) : 0);
427
+ let guest = (parts.length >= 10 ? parseInt(parts[9]) : 0);
428
+ let guest_nice = (parts.length >= 11 ? parseInt(parts[10]) : 0);
429
+ return user + nice + system + idle + iowait + irq + softirq + steal + guest + guest_nice;
430
+ }
431
+
432
+ function calcProcStatLinux(line, all, _cpu_old) {
433
+ let statparts = line.replace(/ +/g, ' ').split(')');
434
+ if (statparts.length >= 2) {
435
+ let parts = statparts[1].split(' ');
436
+ if (parts.length >= 16) {
437
+ let pid = parseInt(statparts[0].split(' ')[0]);
438
+ let utime = parseInt(parts[12]);
439
+ let stime = parseInt(parts[13]);
440
+ let cutime = parseInt(parts[14]);
441
+ let cstime = parseInt(parts[15]);
442
+
443
+ // calc
444
+ let cpuu = 0;
445
+ let cpus = 0;
446
+ if (_cpu_old.all > 0 && _cpu_old.list[pid]) {
447
+ cpuu = (utime + cutime - _cpu_old.list[pid].utime - _cpu_old.list[pid].cutime) / (all - _cpu_old.all) * 100; // user
448
+ cpus = (stime + cstime - _cpu_old.list[pid].stime - _cpu_old.list[pid].cstime) / (all - _cpu_old.all) * 100; // system
449
+ } else {
450
+ cpuu = (utime + cutime) / (all) * 100; // user
451
+ cpus = (stime + cstime) / (all) * 100; // system
452
+ }
453
+ return {
454
+ pid: pid,
455
+ utime: utime,
456
+ stime: stime,
457
+ cutime: cutime,
458
+ cstime: cstime,
459
+ cpuu: cpuu,
460
+ cpus: cpus
461
+ };
462
+ } else {
463
+ return {
464
+ pid: 0,
465
+ utime: 0,
466
+ stime: 0,
467
+ cutime: 0,
468
+ cstime: 0,
469
+ cpuu: 0,
470
+ cpus: 0
471
+ };
472
+ }
473
+ } else {
474
+ return {
475
+ pid: 0,
476
+ utime: 0,
477
+ stime: 0,
478
+ cutime: 0,
479
+ cstime: 0,
480
+ cpuu: 0,
481
+ cpus: 0
482
+ };
483
+ }
484
+ }
485
+
486
+ function calcProcStatWin(procStat, all, _cpu_old) {
487
+ // calc
488
+ let cpuu = 0;
489
+ let cpus = 0;
490
+ if (_cpu_old.all > 0 && _cpu_old.list[procStat.pid]) {
491
+ cpuu = (procStat.utime - _cpu_old.list[procStat.pid].utime) / (all - _cpu_old.all) * 100; // user
492
+ cpus = (procStat.stime - _cpu_old.list[procStat.pid].stime) / (all - _cpu_old.all) * 100; // system
493
+ } else {
494
+ cpuu = (procStat.utime) / (all) * 100; // user
495
+ cpus = (procStat.stime) / (all) * 100; // system
496
+ }
497
+ return {
498
+ pid: procStat.pid,
499
+ utime: procStat.utime,
500
+ stime: procStat.stime,
501
+ cpuu: cpuu > 0 ? cpuu : 0,
502
+ cpus: cpus > 0 ? cpus : 0
503
+ };
504
+ }
505
+
506
+
507
+
508
+ // --------------------------
509
+ // running processes
510
+
511
+ function processes(callback) {
512
+
513
+ let parsedhead = [];
514
+
515
+ function getName(command) {
516
+ command = command || '';
517
+ let result = command.split(' ')[0];
518
+ if (result.substr(-1) === ':') {
519
+ result = result.substr(0, result.length - 1);
520
+ }
521
+ if (result.substr(0, 1) !== '[') {
522
+ let parts = result.split('/');
523
+ if (isNaN(parseInt(parts[parts.length - 1]))) {
524
+ result = parts[parts.length - 1];
525
+ } else {
526
+ result = parts[0];
527
+ }
528
+ }
529
+ return result;
530
+ }
531
+
532
+ function parseLine(line) {
533
+
534
+ let offset = 0;
535
+ let offset2 = 0;
536
+
537
+ function checkColumn(i) {
538
+ offset = offset2;
539
+ if (parsedhead[i]) {
540
+ offset2 = line.substring(parsedhead[i].to + offset, 10000).indexOf(' ');
541
+ } else {
542
+ offset2 = 10000;
543
+ }
544
+ }
545
+
546
+ checkColumn(0);
547
+ const pid = parseInt(line.substring(parsedhead[0].from + offset, parsedhead[0].to + offset2));
548
+ checkColumn(1);
549
+ const ppid = parseInt(line.substring(parsedhead[1].from + offset, parsedhead[1].to + offset2));
550
+ checkColumn(2);
551
+ const cpu = parseFloat(line.substring(parsedhead[2].from + offset, parsedhead[2].to + offset2).replace(/,/g, '.'));
552
+ checkColumn(3);
553
+ const mem = parseFloat(line.substring(parsedhead[3].from + offset, parsedhead[3].to + offset2).replace(/,/g, '.'));
554
+ checkColumn(4);
555
+ const priority = parseInt(line.substring(parsedhead[4].from + offset, parsedhead[4].to + offset2));
556
+ checkColumn(5);
557
+ const vsz = parseInt(line.substring(parsedhead[5].from + offset, parsedhead[5].to + offset2));
558
+ checkColumn(6);
559
+ const rss = parseInt(line.substring(parsedhead[6].from + offset, parsedhead[6].to + offset2));
560
+ checkColumn(7);
561
+ const nice = parseInt(line.substring(parsedhead[7].from + offset, parsedhead[7].to + offset2)) || 0;
562
+ checkColumn(8);
563
+ 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());
564
+ checkColumn(9);
565
+ let state = line.substring(parsedhead[9].from + offset, parsedhead[9].to + offset2).trim();
566
+ 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')))))));
567
+ checkColumn(10);
568
+ let tty = line.substring(parsedhead[10].from + offset, parsedhead[10].to + offset2).trim();
569
+ if (tty === '?' || tty === '??') { tty = ''; }
570
+ checkColumn(11);
571
+ const user = line.substring(parsedhead[11].from + offset, parsedhead[11].to + offset2).trim();
572
+ checkColumn(12);
573
+ let cmdPath = '';
574
+ let command = '';
575
+ let params = '';
576
+ let fullcommand = line.substring(parsedhead[12].from + offset, parsedhead[12].to + offset2).trim();
577
+ if (fullcommand.substr(fullcommand.length - 1) === ']') { fullcommand = fullcommand.slice(0, -1); }
578
+ if (fullcommand.substr(0, 1) === '[') { command = fullcommand.substring(1); }
579
+ else {
580
+ const p1 = fullcommand.indexOf('(');
581
+ const p2 = fullcommand.indexOf(')');
582
+ const p3 = fullcommand.indexOf('/');
583
+ const p4 = fullcommand.indexOf(':');
584
+ if (p1 < p2 && p1 < p3 && p3 < p2) {
585
+ command = fullcommand.split(' ')[0];
586
+ command = command.replace(/:/g, '');
587
+ } else {
588
+ if (p4 > 0 && (p3 === -1 || p3 > 3)) {
589
+ command = fullcommand.split(' ')[0];
590
+ command = command.replace(/:/g, '');
591
+ } else {
592
+ // try to figure out where parameter starts
593
+ let firstParamPos = fullcommand.indexOf(' -');
594
+ let firstParamPathPos = fullcommand.indexOf(' /');
595
+ firstParamPos = (firstParamPos >= 0 ? firstParamPos : 10000);
596
+ firstParamPathPos = (firstParamPathPos >= 0 ? firstParamPathPos : 10000);
597
+ const firstPos = Math.min(firstParamPos, firstParamPathPos);
598
+ let tmpCommand = fullcommand.substr(0, firstPos);
599
+ const tmpParams = fullcommand.substr(firstPos);
600
+ const lastSlashPos = tmpCommand.lastIndexOf('/');
601
+ if (lastSlashPos >= 0) {
602
+ cmdPath = tmpCommand.substr(0, lastSlashPos);
603
+ tmpCommand = tmpCommand.substr(lastSlashPos + 1);
604
+ }
605
+
606
+ if (firstPos === 10000 && tmpCommand.indexOf(' ') > -1) {
607
+ const parts = tmpCommand.split(' ');
608
+ if (fs.existsSync(path.join(cmdPath, parts[0]))) {
609
+ command = parts.shift();
610
+ params = (parts.join(' ') + ' ' + tmpParams).trim();
611
+ } else {
612
+ command = tmpCommand.trim();
613
+ params = tmpParams.trim();
614
+ }
615
+ } else {
616
+ command = tmpCommand.trim();
617
+ params = tmpParams.trim();
618
+ }
619
+ }
620
+ }
621
+
622
+ }
623
+
624
+ return ({
625
+ pid: pid,
626
+ parentPid: ppid,
627
+ name: _linux ? getName(command) : command,
628
+ cpu: cpu,
629
+ cpuu: 0,
630
+ cpus: 0,
631
+ mem: mem,
632
+ priority: priority,
633
+ memVsz: vsz,
634
+ memRss: rss,
635
+ nice: nice,
636
+ started: started,
637
+ state: state,
638
+ tty: tty,
639
+ user: user,
640
+ command: command,
641
+ params: params,
642
+ path: cmdPath
643
+ });
644
+ }
645
+
646
+ function parseProcesses(lines) {
647
+ let result = [];
648
+ if (lines.length > 1) {
649
+ let head = lines[0];
650
+ parsedhead = util.parseHead(head, 8);
651
+ lines.shift();
652
+ lines.forEach(function (line) {
653
+ if (line.trim() !== '') {
654
+ result.push(parseLine(line));
655
+ }
656
+ });
657
+ }
658
+ return result;
659
+ }
660
+ function parseProcesses2(lines) {
661
+
662
+ function formatDateTime(time) {
663
+ const month = ('0' + (time.getMonth() + 1).toString()).slice(-2);
664
+ const year = time.getFullYear().toString();
665
+ const day = ('0' + time.getDate().toString()).slice(-2);
666
+ const hours = ('0' + time.getHours().toString()).slice(-2);
667
+ const mins = ('0' + time.getMinutes().toString()).slice(-2);
668
+ const secs = ('0' + time.getSeconds().toString()).slice(-2);
669
+
670
+ return (year + '-' + month + '-' + day + ' ' + hours + ':' + mins + ':' + secs);
671
+ }
672
+
673
+ function parseElapsed(etime) {
674
+ let started = '';
675
+ if (etime.indexOf('d') >= 0) {
676
+ const elapsed_parts = etime.split('d');
677
+ started = formatDateTime(new Date(Date.now() - (elapsed_parts[0] * 24 + elapsed_parts[1] * 1) * 60 * 60 * 1000));
678
+ } else if (etime.indexOf('h') >= 0) {
679
+ const elapsed_parts = etime.split('h');
680
+ started = formatDateTime(new Date(Date.now() - (elapsed_parts[0] * 60 + elapsed_parts[1] * 1) * 60 * 1000));
681
+ } else if (etime.indexOf(':') >= 0) {
682
+ const elapsed_parts = etime.split(':');
683
+ started = formatDateTime(new Date(Date.now() - (elapsed_parts.length > 1 ? (elapsed_parts[0] * 60 + elapsed_parts[1]) * 1000 : elapsed_parts[0] * 1000)));
684
+ }
685
+ return started;
686
+ }
687
+
688
+ let result = [];
689
+ lines.forEach(function (line) {
690
+ if (line.trim() !== '') {
691
+ line = line.trim().replace(/ +/g, ' ').replace(/,+/g, '.');
692
+ const parts = line.split(' ');
693
+ const command = parts.slice(9).join(' ');
694
+ const pmem = parseFloat((1.0 * parseInt(parts[3]) * 1024 / os.totalmem()).toFixed(1));
695
+ const started = parseElapsed(parts[5]);
696
+
697
+ result.push({
698
+ pid: parseInt(parts[0]),
699
+ parentPid: parseInt(parts[1]),
700
+ name: getName(command),
701
+ cpu: 0,
702
+ cpuu: 0,
703
+ cpus: 0,
704
+ mem: pmem,
705
+ priority: 0,
706
+ memVsz: parseInt(parts[2]),
707
+ memRss: parseInt(parts[3]),
708
+ nice: parseInt(parts[4]),
709
+ started: started,
710
+ 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'))))))),
711
+ tty: parts[7],
712
+ user: parts[8],
713
+ command: command
714
+ });
715
+ }
716
+ });
717
+ return result;
718
+ }
719
+
720
+ return new Promise((resolve) => {
721
+ process.nextTick(() => {
722
+ let result = {
723
+ all: 0,
724
+ running: 0,
725
+ blocked: 0,
726
+ sleeping: 0,
727
+ unknown: 0,
728
+ list: []
729
+ };
730
+
731
+ let cmd = '';
732
+
733
+ if ((_processes_cpu.ms && Date.now() - _processes_cpu.ms >= 500) || _processes_cpu.ms === 0) {
734
+ if (_linux || _freebsd || _openbsd || _netbsd || _darwin || _sunos) {
735
+ 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'; }
736
+ 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'; }
737
+ 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'; }
738
+ if (_sunos) { cmd = 'ps -Ao pid,ppid,pcpu,pmem,pri,vsz,rss,nice,stime,s,tty,user,comm'; }
739
+ exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
740
+ if (!error && stdout.toString().trim()) {
741
+ result.list = (parseProcesses(stdout.toString().split('\n'))).slice();
742
+ result.all = result.list.length;
743
+ result.running = result.list.filter(function (e) {
744
+ return e.state === 'running';
745
+ }).length;
746
+ result.blocked = result.list.filter(function (e) {
747
+ return e.state === 'blocked';
748
+ }).length;
749
+ result.sleeping = result.list.filter(function (e) {
750
+ return e.state === 'sleeping';
751
+ }).length;
752
+
753
+ if (_linux) {
754
+ // calc process_cpu - ps is not accurate in linux!
755
+ cmd = 'cat /proc/stat | grep "cpu "';
756
+ result.list.forEach((element) => {
757
+ cmd += (';cat /proc/' + element.pid + '/stat');
758
+ });
759
+ exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
760
+ let curr_processes = stdout.toString().split('\n');
761
+
762
+ // first line (all - /proc/stat)
763
+ let all = parseProcStat(curr_processes.shift());
764
+
765
+ // process
766
+ let list_new = {};
767
+ let resultProcess = {};
768
+ curr_processes.forEach((element) => {
769
+ resultProcess = calcProcStatLinux(element, all, _processes_cpu);
770
+
771
+ if (resultProcess.pid) {
772
+
773
+ // store pcpu in outer array
774
+ let listPos = result.list.map(function (e) { return e.pid; }).indexOf(resultProcess.pid);
775
+ if (listPos >= 0) {
776
+ result.list[listPos].cpu = resultProcess.cpuu + resultProcess.cpus;
777
+ result.list[listPos].cpuu = resultProcess.cpuu;
778
+ result.list[listPos].cpus = resultProcess.cpus;
779
+ }
780
+
781
+ // save new values
782
+ list_new[resultProcess.pid] = {
783
+ cpuu: resultProcess.cpuu,
784
+ cpus: resultProcess.cpus,
785
+ utime: resultProcess.utime,
786
+ stime: resultProcess.stime,
787
+ cutime: resultProcess.cutime,
788
+ cstime: resultProcess.cstime
789
+ };
790
+ }
791
+ });
792
+
793
+ // store old values
794
+ _processes_cpu.all = all;
795
+ _processes_cpu.list = Object.assign({}, list_new);
796
+ _processes_cpu.ms = Date.now() - _processes_cpu.ms;
797
+ _processes_cpu.result = Object.assign({}, result);
798
+ if (callback) { callback(result); }
799
+ resolve(result);
800
+ });
801
+ } else {
802
+ if (callback) { callback(result); }
803
+ resolve(result);
804
+ }
805
+ } else {
806
+ cmd = 'ps -o pid,ppid,vsz,rss,nice,etime,stat,tty,user,comm';
807
+ if (_sunos) {
808
+ cmd = 'ps -o pid,ppid,vsz,rss,nice,etime,s,tty,user,comm';
809
+ }
810
+ exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
811
+ if (!error) {
812
+ let lines = stdout.toString().split('\n');
813
+ lines.shift();
814
+
815
+ result.list = parseProcesses2(lines).slice();
816
+ result.all = result.list.length;
817
+ result.running = result.list.filter(function (e) {
818
+ return e.state === 'running';
819
+ }).length;
820
+ result.blocked = result.list.filter(function (e) {
821
+ return e.state === 'blocked';
822
+ }).length;
823
+ result.sleeping = result.list.filter(function (e) {
824
+ return e.state === 'sleeping';
825
+ }).length;
826
+ if (callback) { callback(result); }
827
+ resolve(result);
828
+ } else {
829
+ if (callback) { callback(result); }
830
+ resolve(result);
831
+ }
832
+ });
833
+ }
834
+ });
835
+ } else if (_windows) {
836
+ try {
837
+ util.powerShell('Get-CimInstance Win32_Process | select-Object ProcessId,ParentProcessId,ExecutionState,Caption,CommandLine,ExecutablePath,UserModeTime,KernelModeTime,WorkingSetSize,Priority,PageFileUsage, @{n="CreationDate";e={$_.CreationDate.ToString("yyyy-MM-dd HH:mm:ss")}} | fl').then((stdout, error) => {
838
+ if (!error) {
839
+ let processSections = stdout.split(/\n\s*\n/);
840
+ let procs = [];
841
+ let procStats = [];
842
+ let list_new = {};
843
+ let allcpuu = 0;
844
+ let allcpus = 0;
845
+ processSections.forEach((element) => {
846
+ if (element.trim() !== '') {
847
+ let lines = element.trim().split('\r\n');
848
+ let pid = parseInt(util.getValue(lines, 'ProcessId', ':', true), 10);
849
+ let parentPid = parseInt(util.getValue(lines, 'ParentProcessId', ':', true), 10);
850
+ let statusValue = util.getValue(lines, 'ExecutionState', ':');
851
+ let name = util.getValue(lines, 'Caption', ':', true);
852
+ let commandLine = util.getValue(lines, 'CommandLine', ':', true);
853
+ // get additional command line data
854
+ let additionalCommand = false;
855
+ lines.forEach((line) => {
856
+ if (additionalCommand && line.toLowerCase().startsWith(' ')) {
857
+ commandLine += ' ' + line.trim();
858
+ } else {
859
+ additionalCommand = false;
860
+ }
861
+ if (line.toLowerCase().startsWith('commandline')) {
862
+ additionalCommand = true;
863
+ }
864
+ });
865
+ let commandPath = util.getValue(lines, 'ExecutablePath', ':', true);
866
+ let utime = parseInt(util.getValue(lines, 'UserModeTime', ':', true), 10);
867
+ let stime = parseInt(util.getValue(lines, 'KernelModeTime', ':', true), 10);
868
+ let memw = parseInt(util.getValue(lines, 'WorkingSetSize', ':', true), 10);
869
+ allcpuu = allcpuu + utime;
870
+ allcpus = allcpus + stime;
871
+ result.all++;
872
+ if (!statusValue) { result.unknown++; }
873
+ if (statusValue === '3') { result.running++; }
874
+ if (statusValue === '4' || statusValue === '5') { result.blocked++; }
875
+
876
+ procStats.push({
877
+ pid: pid,
878
+ utime: utime,
879
+ stime: stime,
880
+ cpu: 0,
881
+ cpuu: 0,
882
+ cpus: 0,
883
+ });
884
+ procs.push({
885
+ pid: pid,
886
+ parentPid: parentPid,
887
+ name: name,
888
+ cpu: 0,
889
+ cpuu: 0,
890
+ cpus: 0,
891
+ mem: memw / os.totalmem() * 100,
892
+ priority: parseInt(util.getValue(lines, 'Priority', ':', true), 10),
893
+ memVsz: parseInt(util.getValue(lines, 'PageFileUsage', ':', true), 10),
894
+ memRss: Math.floor(parseInt(util.getValue(lines, 'WorkingSetSize', ':', true), 10) / 1024),
895
+ nice: 0,
896
+ started: util.getValue(lines, 'CreationDate', ':', true),
897
+ state: (!statusValue ? _winStatusValues[0] : _winStatusValues[statusValue]),
898
+ tty: '',
899
+ user: '',
900
+ command: commandLine || name,
901
+ path: commandPath,
902
+ params: ''
903
+ });
904
+ }
905
+ });
906
+
907
+ result.sleeping = result.all - result.running - result.blocked - result.unknown;
908
+ result.list = procs;
909
+ procStats.forEach((element) => {
910
+ let resultProcess = calcProcStatWin(element, allcpuu + allcpus, _processes_cpu);
911
+
912
+ // store pcpu in outer array
913
+ let listPos = result.list.map(function (e) { return e.pid; }).indexOf(resultProcess.pid);
914
+ if (listPos >= 0) {
915
+ result.list[listPos].cpu = resultProcess.cpuu + resultProcess.cpus;
916
+ result.list[listPos].cpuu = resultProcess.cpuu;
917
+ result.list[listPos].cpus = resultProcess.cpus;
918
+ }
919
+
920
+ // save new values
921
+ list_new[resultProcess.pid] = {
922
+ cpuu: resultProcess.cpuu,
923
+ cpus: resultProcess.cpus,
924
+ utime: resultProcess.utime,
925
+ stime: resultProcess.stime
926
+ };
927
+ });
928
+
929
+ // store old values
930
+ _processes_cpu.all = allcpuu + allcpus;
931
+ _processes_cpu.all_utime = allcpuu;
932
+ _processes_cpu.all_stime = allcpus;
933
+ _processes_cpu.list = Object.assign({}, list_new);
934
+ _processes_cpu.ms = Date.now() - _processes_cpu.ms;
935
+ _processes_cpu.result = Object.assign({}, result);
936
+ }
937
+ if (callback) {
938
+ callback(result);
939
+ }
940
+ resolve(result);
941
+ });
942
+ } catch (e) {
943
+ if (callback) { callback(result); }
944
+ resolve(result);
945
+ }
946
+ } else {
947
+ if (callback) { callback(result); }
948
+ resolve(result);
949
+ }
950
+ } else {
951
+ if (callback) { callback(_processes_cpu.result); }
952
+ resolve(_processes_cpu.result);
953
+ }
954
+ });
955
+ });
956
+ }
957
+
958
+ exports.processes = processes;
959
+
960
+ // --------------------------
961
+ // PS - process load
962
+ // get detailed information about a certain process
963
+ // (PID, CPU-Usage %, Mem-Usage %)
964
+
965
+ function processLoad(proc, callback) {
966
+
967
+ // fallback - if only callback is given
968
+ if (util.isFunction(proc) && !callback) {
969
+ callback = proc;
970
+ proc = '';
971
+ }
972
+
973
+ return new Promise((resolve) => {
974
+ process.nextTick(() => {
975
+
976
+ proc = proc || '';
977
+
978
+ if (typeof proc !== 'string') {
979
+ if (callback) { callback([]); }
980
+ return resolve([]);
981
+ }
982
+
983
+ let processesString = '';
984
+ processesString.__proto__.toLowerCase = util.stringToLower;
985
+ processesString.__proto__.replace = util.stringReplace;
986
+ processesString.__proto__.trim = util.stringTrim;
987
+
988
+ const s = util.sanitizeShellString(proc);
989
+ for (let i = 0; i <= util.mathMin(s.length, 2000); i++) {
990
+ if (s[i] !== undefined) {
991
+ processesString = processesString + s[i];
992
+ }
993
+ }
994
+
995
+ processesString = processesString.trim().toLowerCase().replace(/, /g, '|').replace(/,+/g, '|');
996
+ if (processesString === '') {
997
+ processesString = '*';
998
+ }
999
+ if (util.isPrototypePolluted() && processesString !== '*') {
1000
+ processesString = '------';
1001
+ }
1002
+ let processes = processesString.split('|');
1003
+ let result = [];
1004
+
1005
+ const procSanitized = util.isPrototypePolluted() ? '' : util.sanitizeShellString(proc);
1006
+
1007
+ // from here new
1008
+ // let result = {
1009
+ // 'proc': procSanitized,
1010
+ // 'pid': null,
1011
+ // 'cpu': 0,
1012
+ // 'mem': 0
1013
+ // };
1014
+ if (procSanitized && processes.length && processes[0] !== '------') {
1015
+ if (_windows) {
1016
+ try {
1017
+ util.powerShell('Get-CimInstance Win32_Process | select ProcessId,Caption,UserModeTime,KernelModeTime,WorkingSetSize | fl').then((stdout, error) => {
1018
+ if (!error) {
1019
+ let processSections = stdout.split(/\n\s*\n/);
1020
+ let procStats = [];
1021
+ let list_new = {};
1022
+ let allcpuu = 0;
1023
+ let allcpus = 0;
1024
+
1025
+ // go through all processes
1026
+ processSections.forEach((element) => {
1027
+ if (element.trim() !== '') {
1028
+ let lines = element.trim().split('\r\n');
1029
+ let pid = parseInt(util.getValue(lines, 'ProcessId', ':', true), 10);
1030
+ let name = util.getValue(lines, 'Caption', ':', true);
1031
+ let utime = parseInt(util.getValue(lines, 'UserModeTime', ':', true), 10);
1032
+ let stime = parseInt(util.getValue(lines, 'KernelModeTime', ':', true), 10);
1033
+ let mem = parseInt(util.getValue(lines, 'WorkingSetSize', ':', true), 10);
1034
+ allcpuu = allcpuu + utime;
1035
+ allcpus = allcpus + stime;
1036
+
1037
+ procStats.push({
1038
+ pid: pid,
1039
+ name,
1040
+ utime: utime,
1041
+ stime: stime,
1042
+ cpu: 0,
1043
+ cpuu: 0,
1044
+ cpus: 0,
1045
+ mem
1046
+ });
1047
+ let pname = '';
1048
+ let inList = false;
1049
+ processes.forEach(function (proc) {
1050
+ if (name.toLowerCase().indexOf(proc.toLowerCase()) >= 0 && !inList) {
1051
+ inList = true;
1052
+ pname = proc;
1053
+ }
1054
+ });
1055
+
1056
+ if (processesString === '*' || inList) {
1057
+ let processFound = false;
1058
+ result.forEach(function (item) {
1059
+ if (item.proc.toLowerCase() === pname.toLowerCase()) {
1060
+ item.pids.push(pid);
1061
+ item.mem += mem / os.totalmem() * 100;
1062
+ processFound = true;
1063
+ }
1064
+ });
1065
+ if (!processFound) {
1066
+ result.push({
1067
+ proc: pname,
1068
+ pid: pid,
1069
+ pids: [pid],
1070
+ cpu: 0,
1071
+ mem: mem / os.totalmem() * 100
1072
+ });
1073
+ }
1074
+ }
1075
+ }
1076
+ });
1077
+
1078
+ // add missing processes
1079
+ if (processesString !== '*') {
1080
+ let processesMissing = processes.filter(function (name) {
1081
+ return procStats.filter(function (item) { return item.name.toLowerCase().indexOf(name) >= 0; }).length === 0;
1082
+
1083
+ });
1084
+ processesMissing.forEach(function (procName) {
1085
+ result.push({
1086
+ proc: procName,
1087
+ pid: null,
1088
+ pids: [],
1089
+ cpu: 0,
1090
+ mem: 0
1091
+ });
1092
+ });
1093
+ }
1094
+
1095
+ // calculate proc stats for each proc
1096
+ procStats.forEach((element) => {
1097
+ let resultProcess = calcProcStatWin(element, allcpuu + allcpus, _process_cpu);
1098
+
1099
+ let listPos = -1;
1100
+ for (let j = 0; j < result.length; j++) {
1101
+ if (result[j].pid === resultProcess.pid || result[j].pids.indexOf(resultProcess.pid) >= 0) { listPos = j; }
1102
+ }
1103
+ if (listPos >= 0) {
1104
+ result[listPos].cpu += resultProcess.cpuu + resultProcess.cpus;
1105
+ }
1106
+
1107
+ // save new values
1108
+ list_new[resultProcess.pid] = {
1109
+ cpuu: resultProcess.cpuu,
1110
+ cpus: resultProcess.cpus,
1111
+ utime: resultProcess.utime,
1112
+ stime: resultProcess.stime
1113
+ };
1114
+ });
1115
+
1116
+ // store old values
1117
+ _process_cpu.all = allcpuu + allcpus;
1118
+ _process_cpu.all_utime = allcpuu;
1119
+ _process_cpu.all_stime = allcpus;
1120
+ _process_cpu.list = Object.assign({}, list_new);
1121
+ _process_cpu.ms = Date.now() - _process_cpu.ms;
1122
+ _process_cpu.result = JSON.parse(JSON.stringify(result));
1123
+ if (callback) {
1124
+ callback(result);
1125
+ }
1126
+ resolve(result);
1127
+ }
1128
+ });
1129
+ } catch (e) {
1130
+ if (callback) { callback(result); }
1131
+ resolve(result);
1132
+ }
1133
+ }
1134
+
1135
+ if (_darwin || _linux || _freebsd || _openbsd || _netbsd) {
1136
+ const params = ['-axo', 'pid,ppid,pcpu,pmem,comm'];
1137
+ util.execSafe('ps', params).then((stdout) => {
1138
+ if (stdout) {
1139
+ let procStats = [];
1140
+ let lines = stdout.toString().split('\n').filter(function (line) {
1141
+ if (processesString === '*') { return true; }
1142
+ if (line.toLowerCase().indexOf('grep') !== -1) { return false; } // remove this??
1143
+ let found = false;
1144
+ processes.forEach(function (item) {
1145
+ found = found || (line.toLowerCase().indexOf(item.toLowerCase()) >= 0);
1146
+ });
1147
+ return found;
1148
+ });
1149
+
1150
+ lines.forEach(function (line) {
1151
+ let data = line.trim().replace(/ +/g, ' ').split(' ');
1152
+ if (data.length > 4) {
1153
+ procStats.push({
1154
+ name: data[4].substring(data[4].lastIndexOf('/') + 1),
1155
+ pid: parseInt(data[0]) || 0,
1156
+ ppid: parseInt(data[1]) || 0,
1157
+ cpu: parseFloat(data[2].replace(',', '.')),
1158
+ mem: parseFloat(data[3].replace(',', '.'))
1159
+ });
1160
+ }
1161
+ });
1162
+
1163
+ procStats.forEach(function (item) {
1164
+ let listPos = -1;
1165
+ let inList = false;
1166
+ let name = '';
1167
+ for (let j = 0; j < result.length; j++) {
1168
+ if (item.name.toLowerCase().indexOf(result[j].proc.toLowerCase()) >= 0) {
1169
+ listPos = j;
1170
+ }
1171
+ }
1172
+ processes.forEach(function (proc) {
1173
+
1174
+ if (item.name.toLowerCase().indexOf(proc.toLowerCase()) >= 0 && !inList) {
1175
+ inList = true;
1176
+ name = proc;
1177
+ }
1178
+ });
1179
+ if ((processesString === '*') || inList) {
1180
+ if (listPos < 0) {
1181
+ result.push({
1182
+ proc: name,
1183
+ pid: item.pid,
1184
+ pids: [item.pid],
1185
+ cpu: item.cpu,
1186
+ mem: item.mem
1187
+ });
1188
+ } else {
1189
+ if (item.ppid < 10) {
1190
+ result[listPos].pid = item.pid;
1191
+ }
1192
+ result[listPos].pids.push(item.pid);
1193
+ result[listPos].cpu += item.cpu;
1194
+ result[listPos].mem += item.mem;
1195
+ }
1196
+ }
1197
+ });
1198
+
1199
+ if (processesString !== '*') {
1200
+ // add missing processes
1201
+ let processesMissing = processes.filter(function (name) {
1202
+ return procStats.filter(function (item) { return item.name.toLowerCase().indexOf(name) >= 0; }).length === 0;
1203
+ });
1204
+ processesMissing.forEach(function (procName) {
1205
+ result.push({
1206
+ proc: procName,
1207
+ pid: null,
1208
+ pids: [],
1209
+ cpu: 0,
1210
+ mem: 0
1211
+ });
1212
+ });
1213
+ }
1214
+ if (_linux) {
1215
+ // calc process_cpu - ps is not accurate in linux!
1216
+ result.forEach(function (item) {
1217
+ item.cpu = 0;
1218
+ });
1219
+ let cmd = 'cat /proc/stat | grep "cpu "';
1220
+ for (let i in result) {
1221
+ for (let j in result[i].pids) {
1222
+ cmd += (';cat /proc/' + result[i].pids[j] + '/stat');
1223
+ }
1224
+ }
1225
+ exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
1226
+ let curr_processes = stdout.toString().split('\n');
1227
+
1228
+ // first line (all - /proc/stat)
1229
+ let all = parseProcStat(curr_processes.shift());
1230
+
1231
+ // process
1232
+ let list_new = {};
1233
+ let resultProcess = {};
1234
+ curr_processes.forEach((element) => {
1235
+ resultProcess = calcProcStatLinux(element, all, _process_cpu);
1236
+
1237
+ if (resultProcess.pid) {
1238
+
1239
+ // find result item
1240
+ let resultItemId = -1;
1241
+ for (let i in result) {
1242
+ if (result[i].pids.indexOf(resultProcess.pid) >= 0) {
1243
+ resultItemId = i;
1244
+ }
1245
+ }
1246
+ // store pcpu in outer result
1247
+ if (resultItemId >= 0) {
1248
+ result[resultItemId].cpu += resultProcess.cpuu + resultProcess.cpus;
1249
+ }
1250
+
1251
+ // save new values
1252
+ list_new[resultProcess.pid] = {
1253
+ cpuu: resultProcess.cpuu,
1254
+ cpus: resultProcess.cpus,
1255
+ utime: resultProcess.utime,
1256
+ stime: resultProcess.stime,
1257
+ cutime: resultProcess.cutime,
1258
+ cstime: resultProcess.cstime
1259
+ };
1260
+ }
1261
+ });
1262
+
1263
+ result.forEach(function (item) {
1264
+ item.cpu = Math.round(item.cpu * 100) / 100;
1265
+ });
1266
+
1267
+ _process_cpu.all = all;
1268
+ _process_cpu.list = Object.assign({}, list_new);
1269
+ _process_cpu.ms = Date.now() - _process_cpu.ms;
1270
+ _process_cpu.result = Object.assign({}, result);
1271
+ if (callback) { callback(result); }
1272
+ resolve(result);
1273
+ });
1274
+ } else {
1275
+ if (callback) { callback(result); }
1276
+ resolve(result);
1277
+ }
1278
+ } else {
1279
+ if (callback) { callback(result); }
1280
+ resolve(result);
1281
+ }
1282
+ });
1283
+ }
1284
+ }
1285
+ });
1286
+ });
1287
+ }
1288
+
1289
+ exports.processLoad = processLoad;