@depup/systeminformation 5.33.6-depup.0 → 5.33.10-depup.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/changes.json +1 -1
- package/lib/audio.js +10 -5
- package/lib/filesystem.js +91 -13
- package/lib/graphics.js +3 -7
- package/lib/internet.js +6 -0
- package/lib/network.js +4 -4
- package/lib/osinfo.js +33 -65
- package/lib/processes.js +80 -43
- package/lib/wifi.js +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -13,8 +13,8 @@ npm install @depup/systeminformation
|
|
|
13
13
|
|
|
14
14
|
| Field | Value |
|
|
15
15
|
|-------|-------|
|
|
16
|
-
| Original | [systeminformation](https://www.npmjs.com/package/systeminformation) @ 5.33.
|
|
17
|
-
| Processed | 2026-
|
|
16
|
+
| Original | [systeminformation](https://www.npmjs.com/package/systeminformation) @ 5.33.10 |
|
|
17
|
+
| Processed | 2026-09-13 |
|
|
18
18
|
| Smoke test | passed |
|
|
19
19
|
| Deps updated | 0 |
|
|
20
20
|
|
package/changes.json
CHANGED
package/lib/audio.js
CHANGED
|
@@ -55,7 +55,7 @@ function parseAudioType(str, input, output) {
|
|
|
55
55
|
if (str.indexOf('mikr') >= 0) {
|
|
56
56
|
result = 'Microphone';
|
|
57
57
|
}
|
|
58
|
-
if (str.indexOf('phone') >= 0) {
|
|
58
|
+
if (str.indexOf('phone') >= 0 && str.indexOf('headphone') < 0) {
|
|
59
59
|
result = 'Phone';
|
|
60
60
|
}
|
|
61
61
|
if (str.indexOf('controll') >= 0) {
|
|
@@ -111,11 +111,16 @@ function parseLinuxAudioAlsa(stdout) {
|
|
|
111
111
|
const lines = cards.split('\n');
|
|
112
112
|
lines.forEach((line, i) => {
|
|
113
113
|
// ' 1 [Device ]: USB-Audio - USB Audio Device'
|
|
114
|
-
const card = line.match(/^\s*(\d+)\s+\[(.+?)\s*\]:\s*(
|
|
115
|
-
if (card) {
|
|
114
|
+
const card = line.match(/^\s*(\d+)\s+\[(.+?)\s*\]:\s*(.*)$/);
|
|
115
|
+
if (card && card[3].trim()) {
|
|
116
116
|
const index = card[1];
|
|
117
|
-
|
|
118
|
-
const
|
|
117
|
+
// some drivers (e.g. bcm2835) print an unterminated driver string, gluing the name to it
|
|
118
|
+
const sep = card[3].lastIndexOf(' - ');
|
|
119
|
+
const name = (sep >= 0 ? card[3].substring(sep + 3) : card[3]).trim();
|
|
120
|
+
let driver = (sep >= 0 ? card[3].substring(0, sep) : '').trim();
|
|
121
|
+
if (name && driver.endsWith(name)) {
|
|
122
|
+
driver = driver.substring(0, driver.length - name.length).trim();
|
|
123
|
+
}
|
|
119
124
|
// second line holds the long name, which is prefixed with the manufacturer on USB devices
|
|
120
125
|
const longName = (lines[i + 1] || '').trim();
|
|
121
126
|
const manufacturer = longName.indexOf(name) > 0 ? longName.substring(0, longName.indexOf(name)).trim() : '';
|
package/lib/filesystem.js
CHANGED
|
@@ -43,8 +43,20 @@ function fsSize(drive, callback) {
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
let macOsDisks = [];
|
|
46
|
+
const macOsFsTypes = new Map();
|
|
46
47
|
let osMounts = [];
|
|
47
48
|
|
|
49
|
+
// macOS df has no type column, so the type used to be guessed from diskutil - which only ever
|
|
50
|
+
// produced APFS, HFS or NFS and therefore never recognised zfs, exfat, msdos or smbfs. mount
|
|
51
|
+
// knows the real type, so prefer it and keep the old names for the three it could produce.
|
|
52
|
+
function macOsFsType(fs) {
|
|
53
|
+
const type = macOsFsTypes.get(fs);
|
|
54
|
+
if (!type) {
|
|
55
|
+
return getmacOsFsType(fs);
|
|
56
|
+
}
|
|
57
|
+
return type === 'apfs' ? 'APFS' : type === 'hfs' ? 'HFS' : type === 'nfs' ? 'NFS' : type;
|
|
58
|
+
}
|
|
59
|
+
|
|
48
60
|
function getmacOsFsType(fs) {
|
|
49
61
|
if (!fs.startsWith('/')) {
|
|
50
62
|
return 'NFS';
|
|
@@ -86,6 +98,59 @@ function fsSize(drive, callback) {
|
|
|
86
98
|
return lines;
|
|
87
99
|
}
|
|
88
100
|
|
|
101
|
+
// ZFS datasets share the pool, so df only reports what a dataset references itself - a parent
|
|
102
|
+
// holding its data in child datasets looks empty (#1017). Only `zfs list` knows the
|
|
103
|
+
// hierarchical usage, so query it once when a zfs mount is present.
|
|
104
|
+
function applyZfsUsage(data, cb) {
|
|
105
|
+
if (!data.some((item) => item.type === 'zfs')) {
|
|
106
|
+
return cb(data);
|
|
107
|
+
}
|
|
108
|
+
exec('zfs list -H -p -o name,used,avail,mountpoint', { ...util.execOptsLinux, timeout: 5000 }, (error, stdout) => {
|
|
109
|
+
if (error) {
|
|
110
|
+
// a truncated or timed out listing would correct only part of the datasets and leave the
|
|
111
|
+
// rest on their df values - correct none instead, so the result stays consistent
|
|
112
|
+
return cb(data);
|
|
113
|
+
}
|
|
114
|
+
const byMount = Object.create(null);
|
|
115
|
+
const byName = Object.create(null);
|
|
116
|
+
(stdout || '')
|
|
117
|
+
.toString()
|
|
118
|
+
.split('\n')
|
|
119
|
+
.forEach((line) => {
|
|
120
|
+
const parts = line.split('\t');
|
|
121
|
+
if (parts.length < 4) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
const entry = { used: parseInt(parts[1], 10), available: parseInt(parts[2], 10) };
|
|
125
|
+
if (isNaN(entry.used) || isNaN(entry.available)) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
byName[parts[0]] = entry;
|
|
129
|
+
const mount = parts[3].trim();
|
|
130
|
+
// several datasets can carry the same mountpoint (root-on-zfs boot environments all
|
|
131
|
+
// declare "/"), so the mount index is only a fallback - keep the first one
|
|
132
|
+
if (mount.startsWith('/') && !byMount[mount]) {
|
|
133
|
+
byMount[mount] = entry;
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
data.forEach((item) => {
|
|
137
|
+
if (item.type !== 'zfs') {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
// the fs column is the exact dataset name and therefore unambiguous, unlike the mountpoint
|
|
141
|
+
const dataset = byName[item.fs] || byMount[item.mount];
|
|
142
|
+
if (!dataset || !(dataset.used + dataset.available)) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
item.used = dataset.used;
|
|
146
|
+
item.available = dataset.available;
|
|
147
|
+
item.size = dataset.used + dataset.available;
|
|
148
|
+
item.use = parseFloat(((100.0 * dataset.used) / item.size).toFixed(2));
|
|
149
|
+
});
|
|
150
|
+
cb(data);
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
89
154
|
function parseDf(lines) {
|
|
90
155
|
const data = [];
|
|
91
156
|
// filesystem (first column) and mount point (last column) may contain spaces:
|
|
@@ -98,7 +163,7 @@ function fsSize(drive, callback) {
|
|
|
98
163
|
const parts = line.trim().match(hasType ? dfWithType : dfNoType);
|
|
99
164
|
if (parts && (parts[1].startsWith('/') || parts[hasType ? 6 : 5] === '/' || parts[1].indexOf('/') > 0 || parts[1].indexOf(':') === 1 || (!_darwin && !isLinuxTmpFs(parts[2])))) {
|
|
100
165
|
const fs = parts[1];
|
|
101
|
-
const fsType = hasType ? parts[2] :
|
|
166
|
+
const fsType = hasType ? parts[2] : macOsFsType(parts[1]);
|
|
102
167
|
const size = parseInt(parts[hasType ? 3 : 2], 10) * 1024;
|
|
103
168
|
const used = parseInt(parts[hasType ? 4 : 3], 10) * 1024;
|
|
104
169
|
const available = parseInt(parts[hasType ? 5 : 4], 10) * 1024;
|
|
@@ -142,11 +207,16 @@ function fsSize(drive, callback) {
|
|
|
142
207
|
execSync('mount')
|
|
143
208
|
.toString()
|
|
144
209
|
.split('\n')
|
|
145
|
-
.filter((line) => {
|
|
146
|
-
return line.startsWith('/');
|
|
147
|
-
})
|
|
148
210
|
.forEach((line) => {
|
|
149
|
-
|
|
211
|
+
// mount output: "<fs> on <mountpoint> (<type>, <options>)"
|
|
212
|
+
const fs = line.split(' ')[0];
|
|
213
|
+
const type = line.match(/\(([^),]+)[^)]*\)$/);
|
|
214
|
+
if (fs && type) {
|
|
215
|
+
macOsFsTypes.set(fs, type[1].trim().toLowerCase());
|
|
216
|
+
}
|
|
217
|
+
if (line.startsWith('/')) {
|
|
218
|
+
osMounts[fs] = line.toLowerCase().indexOf('read-only') === -1;
|
|
219
|
+
}
|
|
150
220
|
});
|
|
151
221
|
} catch {
|
|
152
222
|
util.noop();
|
|
@@ -195,19 +265,23 @@ function fsSize(drive, callback) {
|
|
|
195
265
|
});
|
|
196
266
|
}
|
|
197
267
|
if ((!error || data.length) && stdout.toString().trim() !== '') {
|
|
198
|
-
|
|
199
|
-
callback
|
|
200
|
-
|
|
201
|
-
|
|
268
|
+
applyZfsUsage(data, (data) => {
|
|
269
|
+
if (callback) {
|
|
270
|
+
callback(data);
|
|
271
|
+
}
|
|
272
|
+
resolve(data);
|
|
273
|
+
});
|
|
202
274
|
} else {
|
|
203
275
|
exec('df -kPT 2>/dev/null', { maxBuffer: 1024 * 1024 }, (error, stdout) => {
|
|
204
276
|
// fixed issue alpine fallback
|
|
205
277
|
const lines = filterLines(stdout);
|
|
206
278
|
data = parseDf(lines);
|
|
207
|
-
|
|
208
|
-
callback
|
|
209
|
-
|
|
210
|
-
|
|
279
|
+
applyZfsUsage(data, (data) => {
|
|
280
|
+
if (callback) {
|
|
281
|
+
callback(data);
|
|
282
|
+
}
|
|
283
|
+
resolve(data);
|
|
284
|
+
});
|
|
211
285
|
});
|
|
212
286
|
}
|
|
213
287
|
});
|
|
@@ -1722,6 +1796,10 @@ function diskLayout(callback) {
|
|
|
1722
1796
|
const smartDev = JSON.parse(execSync('smartctl --scan -j').toString());
|
|
1723
1797
|
if (smartDev && smartDev.devices && smartDev.devices.length > 0) {
|
|
1724
1798
|
smartDev.devices.forEach((dev) => {
|
|
1799
|
+
// device names come from smartctl output - never let anything but a plain path reach the shell
|
|
1800
|
+
if (!/^[\w/.,:\\-]+$/.test(String(dev.name || ''))) {
|
|
1801
|
+
return;
|
|
1802
|
+
}
|
|
1725
1803
|
workload.push(execPromiseSave(`smartctl -j -a ${dev.name}`, util.execOptsWin));
|
|
1726
1804
|
});
|
|
1727
1805
|
}
|
package/lib/graphics.js
CHANGED
|
@@ -17,6 +17,7 @@ const fs = require('fs');
|
|
|
17
17
|
const path = require('path');
|
|
18
18
|
const exec = require('child_process').exec;
|
|
19
19
|
const execSync = require('child_process').execSync;
|
|
20
|
+
const execFileSync = require('child_process').execFileSync;
|
|
20
21
|
const util = require('./util');
|
|
21
22
|
|
|
22
23
|
const _platform = process.platform;
|
|
@@ -481,14 +482,9 @@ function graphics(callback) {
|
|
|
481
482
|
if (nvidiaSmiExe) {
|
|
482
483
|
const nvidiaSmiOpts =
|
|
483
484
|
'--query-gpu=driver_version,pci.sub_device_id,name,pci.bus_id,fan.speed,memory.total,memory.used,memory.free,utilization.gpu,utilization.memory,temperature.gpu,temperature.memory,power.draw,power.limit,clocks.gr,clocks.mem --format=csv,noheader,nounits';
|
|
484
|
-
|
|
485
|
-
if (_linux) {
|
|
486
|
-
options.stdio = ['pipe', 'pipe', 'ignore'];
|
|
487
|
-
}
|
|
485
|
+
options.stdio = ['pipe', 'pipe', 'ignore'];
|
|
488
486
|
try {
|
|
489
|
-
|
|
490
|
-
const res = execSync(sanitized, options).toString();
|
|
491
|
-
return res;
|
|
487
|
+
return execFileSync(nvidiaSmiExe, nvidiaSmiOpts.split(' '), options).toString();
|
|
492
488
|
} catch {
|
|
493
489
|
util.noop();
|
|
494
490
|
}
|
package/lib/internet.js
CHANGED
|
@@ -166,6 +166,12 @@ function inetLatency(host, callback) {
|
|
|
166
166
|
}
|
|
167
167
|
return resolve(null);
|
|
168
168
|
}
|
|
169
|
+
if (hostSanitized.startsWith('-')) {
|
|
170
|
+
if (callback) {
|
|
171
|
+
callback(null);
|
|
172
|
+
}
|
|
173
|
+
return resolve(null);
|
|
174
|
+
}
|
|
169
175
|
let params;
|
|
170
176
|
if (_linux || _freebsd || _openbsd || _netbsd || _darwin) {
|
|
171
177
|
if (_linux) {
|
package/lib/network.js
CHANGED
|
@@ -368,8 +368,8 @@ function getWindowsWiredProfilesInformation() {
|
|
|
368
368
|
|
|
369
369
|
function getWindowsWirelessIfaceSSID(interfaceName) {
|
|
370
370
|
try {
|
|
371
|
-
const result =
|
|
372
|
-
const SSID = result.split('\r\n').
|
|
371
|
+
const result = execFileSync('netsh', ['wlan', 'show', 'interface', `name=${util.sanitizeString(interfaceName)}`], util.execOptsWin).toString();
|
|
372
|
+
const SSID = result.split('\r\n').find((l) => l.includes('SSID')) || '';
|
|
373
373
|
const parseSSID = SSID.split(':').pop().trim();
|
|
374
374
|
return parseSSID;
|
|
375
375
|
} catch {
|
|
@@ -420,7 +420,7 @@ function getWindowsIEEE8021x(connectionType, iface, ifaces) {
|
|
|
420
420
|
const SSID = getWindowsWirelessIfaceSSID(iface);
|
|
421
421
|
if (SSID !== 'Unknown') {
|
|
422
422
|
const ifaceSanitized = util.sanitizeString(SSID);
|
|
423
|
-
const profiles =
|
|
423
|
+
const profiles = execFileSync('netsh', ['wlan', 'show', 'profiles', ifaceSanitized], util.execOptsWin).toString().split('\r\n');
|
|
424
424
|
i8021xState = (profiles.find((l) => l.indexOf('802.1X') >= 0) || '').trim();
|
|
425
425
|
i8021xProtocol = (profiles.find((l) => l.indexOf('EAP') >= 0) || '').trim();
|
|
426
426
|
}
|
|
@@ -943,7 +943,7 @@ function networkInterfaces(callback, rescan, defaultString) {
|
|
|
943
943
|
ip6subnet = ip6linksubnet;
|
|
944
944
|
}
|
|
945
945
|
const iface = dev.split(':')[0].trim();
|
|
946
|
-
const ifaceSanitized = util.sanitizeString(iface);
|
|
946
|
+
const ifaceSanitized = util.sanitizeString(iface, true);
|
|
947
947
|
const cmd = `echo -n "addr_assign_type: "; cat /sys/class/net/${ifaceSanitized}/addr_assign_type 2>/dev/null; echo;
|
|
948
948
|
echo -n "address: "; cat /sys/class/net/${ifaceSanitized}/address 2>/dev/null; echo;
|
|
949
949
|
echo -n "addr_len: "; cat /sys/class/net/${ifaceSanitized}/addr_len 2>/dev/null; echo;
|
package/lib/osinfo.js
CHANGED
|
@@ -18,7 +18,6 @@ const fs = require('fs');
|
|
|
18
18
|
const util = require('./util');
|
|
19
19
|
const exec = require('child_process').exec;
|
|
20
20
|
const execSync = require('child_process').execSync;
|
|
21
|
-
const execFile = require('child_process').execFile;
|
|
22
21
|
|
|
23
22
|
const _platform = process.platform;
|
|
24
23
|
|
|
@@ -775,78 +774,47 @@ function versions(apps, callback) {
|
|
|
775
774
|
});
|
|
776
775
|
}
|
|
777
776
|
if ({}.hasOwnProperty.call(appsObj.versions, 'postgresql')) {
|
|
778
|
-
if (
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
.
|
|
784
|
-
.
|
|
785
|
-
.
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
if (!error) {
|
|
790
|
-
const postgresql = stdout.toString().split('\n')[0].split(' ') || [];
|
|
791
|
-
appsObj.versions.postgresql = postgresql.length ? postgresql[postgresql.length - 1] : '';
|
|
777
|
+
if (_windows) {
|
|
778
|
+
util.powerShell('Get-CimInstance Win32_Service | select caption | fl').then((stdout) => {
|
|
779
|
+
let serviceSections = stdout.split(/\n\s*\n/);
|
|
780
|
+
serviceSections.forEach((item) => {
|
|
781
|
+
if (item.trim() !== '') {
|
|
782
|
+
let lines = item.trim().split('\r\n');
|
|
783
|
+
let srvCaption = util.getValue(lines, 'caption', ':', true).toLowerCase();
|
|
784
|
+
if (srvCaption.indexOf('postgresql') > -1) {
|
|
785
|
+
const parts = srvCaption.split(' server ');
|
|
786
|
+
if (parts.length > 1) {
|
|
787
|
+
appsObj.versions.postgresql = parts[1];
|
|
792
788
|
}
|
|
793
|
-
functionProcessed();
|
|
794
|
-
});
|
|
795
|
-
} else {
|
|
796
|
-
functionProcessed();
|
|
797
|
-
}
|
|
798
|
-
} else {
|
|
799
|
-
exec('psql -V', (error, stdout) => {
|
|
800
|
-
if (!error) {
|
|
801
|
-
const postgresql = stdout.toString().split('\n')[0].split(' ') || [];
|
|
802
|
-
appsObj.versions.postgresql = postgresql.length ? postgresql[postgresql.length - 1] : '';
|
|
803
|
-
appsObj.versions.postgresql = appsObj.versions.postgresql.split('-')[0];
|
|
804
789
|
}
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
790
|
+
}
|
|
791
|
+
});
|
|
792
|
+
functionProcessed();
|
|
808
793
|
});
|
|
809
794
|
} else {
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
});
|
|
827
|
-
} else {
|
|
828
|
-
exec('postgres -V', (error, stdout) => {
|
|
829
|
-
if (!error) {
|
|
830
|
-
const postgresql = stdout.toString().split('\n')[0].split(' ') || [];
|
|
831
|
-
appsObj.versions.postgresql = postgresql.length ? postgresql[postgresql.length - 1] : '';
|
|
832
|
-
if (appsObj.versions.postgresql.includes('(') && postgresql.length >= 2 && !postgresql[postgresql.length - 2].includes('(')) {
|
|
833
|
-
appsObj.versions.postgresql = postgresql[postgresql.length - 2];
|
|
834
|
-
}
|
|
795
|
+
const parsePostgres = (stdout) => {
|
|
796
|
+
const postgresql = stdout.toString().split('\n')[0].split(' ') || [];
|
|
797
|
+
let version = postgresql.length ? postgresql[postgresql.length - 1] : '';
|
|
798
|
+
if (version.includes('(') && postgresql.length >= 2 && !postgresql[postgresql.length - 2].includes('(')) {
|
|
799
|
+
version = postgresql[postgresql.length - 2];
|
|
800
|
+
}
|
|
801
|
+
return version.split('-')[0];
|
|
802
|
+
};
|
|
803
|
+
// no `locate`: its output is any user-writable path and must not be executed
|
|
804
|
+
const tryPostgres = (cmds) => {
|
|
805
|
+
if (!cmds.length) {
|
|
806
|
+
return functionProcessed();
|
|
807
|
+
}
|
|
808
|
+
exec(cmds[0], (error, stdout) => {
|
|
809
|
+
if (!error && stdout.toString().trim()) {
|
|
810
|
+
appsObj.versions.postgresql = parsePostgres(stdout);
|
|
835
811
|
functionProcessed();
|
|
836
812
|
} else {
|
|
837
|
-
|
|
838
|
-
if (!error) {
|
|
839
|
-
const postgresql = stdout.toString().split('\n')[0].split(' ') || [];
|
|
840
|
-
appsObj.versions.postgresql = postgresql.length ? postgresql[postgresql.length - 1] : '';
|
|
841
|
-
if (appsObj.versions.postgresql.includes('(') && postgresql.length >= 2 && !postgresql[postgresql.length - 2].includes('(')) {
|
|
842
|
-
appsObj.versions.postgresql = postgresql[postgresql.length - 2];
|
|
843
|
-
}
|
|
844
|
-
}
|
|
845
|
-
functionProcessed();
|
|
846
|
-
});
|
|
813
|
+
tryPostgres(cmds.slice(1));
|
|
847
814
|
}
|
|
848
815
|
});
|
|
849
|
-
}
|
|
816
|
+
};
|
|
817
|
+
tryPostgres(['postgres -V', 'pg_config --version', 'psql -V']);
|
|
850
818
|
}
|
|
851
819
|
}
|
|
852
820
|
if ({}.hasOwnProperty.call(appsObj.versions, 'perl')) {
|
package/lib/processes.js
CHANGED
|
@@ -261,12 +261,20 @@ function services(srv, callback) {
|
|
|
261
261
|
});
|
|
262
262
|
if (_linux) {
|
|
263
263
|
// calc process_cpu - ps is not accurate in linux!
|
|
264
|
+
// ps pcpu is a lifetime average, the /proc values below are an interval share -
|
|
265
|
+
// drop the ps seed instead of adding both (#1007)
|
|
266
|
+
result.forEach((item) => {
|
|
267
|
+
item.cpu = 0;
|
|
268
|
+
});
|
|
264
269
|
let cmd = 'cat /proc/stat | grep "cpu "';
|
|
265
270
|
for (let i in result) {
|
|
266
271
|
for (let j in result[i].pids) {
|
|
267
272
|
cmd += ';cat /proc/' + result[i].pids[j] + '/stat';
|
|
268
273
|
}
|
|
269
274
|
}
|
|
275
|
+
// freeze the baseline before the async call - a concurrent call overwrites _services_cpu
|
|
276
|
+
// and would leave this one dividing by a few jiffies (#1007)
|
|
277
|
+
const cpuBaseline = Object.assign({}, _services_cpu);
|
|
270
278
|
exec(cmd, { maxBuffer: 1024 * 102400 }, function (error, stdout) {
|
|
271
279
|
let curr_processes = stdout.toString().split('\n');
|
|
272
280
|
|
|
@@ -277,7 +285,7 @@ function services(srv, callback) {
|
|
|
277
285
|
let list_new = {};
|
|
278
286
|
let resultProcess = {};
|
|
279
287
|
curr_processes.forEach((element) => {
|
|
280
|
-
resultProcess = calcProcStatLinux(element, all,
|
|
288
|
+
resultProcess = calcProcStatLinux(element, all, cpuBaseline);
|
|
281
289
|
|
|
282
290
|
if (resultProcess.pid) {
|
|
283
291
|
let listPos = -1;
|
|
@@ -297,9 +305,7 @@ function services(srv, callback) {
|
|
|
297
305
|
cpuu: resultProcess.cpuu,
|
|
298
306
|
cpus: resultProcess.cpus,
|
|
299
307
|
utime: resultProcess.utime,
|
|
300
|
-
stime: resultProcess.stime
|
|
301
|
-
cutime: resultProcess.cutime,
|
|
302
|
-
cstime: resultProcess.cstime
|
|
308
|
+
stime: resultProcess.stime
|
|
303
309
|
};
|
|
304
310
|
}
|
|
305
311
|
});
|
|
@@ -474,6 +480,19 @@ function parseProcStat(line) {
|
|
|
474
480
|
return user + nice + system + idle + iowait + irq + softirq + steal + guest + guest_nice;
|
|
475
481
|
}
|
|
476
482
|
|
|
483
|
+
// drops NaN/Infinity/negative values and scales cpuu + cpus down proportionally
|
|
484
|
+
// if their sum exceeds 100 (normalized against all cores)
|
|
485
|
+
function clampCpuPair(cpuu, cpus) {
|
|
486
|
+
if (!isFinite(cpuu) || cpuu < 0) { cpuu = 0; }
|
|
487
|
+
if (!isFinite(cpus) || cpus < 0) { cpus = 0; }
|
|
488
|
+
const total = cpuu + cpus;
|
|
489
|
+
if (total > 100) {
|
|
490
|
+
cpuu = (cpuu / total) * 100;
|
|
491
|
+
cpus = (cpus / total) * 100;
|
|
492
|
+
}
|
|
493
|
+
return { cpuu: cpuu, cpus: cpus };
|
|
494
|
+
}
|
|
495
|
+
|
|
477
496
|
function calcProcStatLinux(line, all, _cpu_old) {
|
|
478
497
|
let statparts = line.replace(/ +/g, ' ').split(')');
|
|
479
498
|
if (statparts.length >= 2) {
|
|
@@ -482,35 +501,34 @@ function calcProcStatLinux(line, all, _cpu_old) {
|
|
|
482
501
|
let pid = parseInt(statparts[0].split(' ')[0]);
|
|
483
502
|
let utime = parseInt(parts[12]);
|
|
484
503
|
let stime = parseInt(parts[13]);
|
|
485
|
-
let cutime = parseInt(parts[14]);
|
|
486
|
-
let cstime = parseInt(parts[15]);
|
|
487
504
|
|
|
488
|
-
// calc
|
|
505
|
+
// calc - child times (cutime/cstime) are deliberately left out: reaping a child adds its
|
|
506
|
+
// whole lifetime in one interval, which is what produced the >100% spikes in #1007.
|
|
507
|
+
// top, htop and Task Manager exclude them too.
|
|
489
508
|
let cpuu = 0;
|
|
490
509
|
let cpus = 0;
|
|
491
510
|
if (_cpu_old.all > 0 && _cpu_old.list[pid]) {
|
|
492
|
-
|
|
493
|
-
|
|
511
|
+
const delta = all - _cpu_old.all;
|
|
512
|
+
cpuu = delta > 0 ? ((utime - _cpu_old.list[pid].utime) / delta) * 100 : 0; // user
|
|
513
|
+
cpus = delta > 0 ? ((stime - _cpu_old.list[pid].stime) / delta) * 100 : 0; // system
|
|
494
514
|
} else {
|
|
495
|
-
cpuu = (
|
|
496
|
-
cpus = (
|
|
515
|
+
cpuu = all > 0 ? (utime / all) * 100 : 0; // user
|
|
516
|
+
cpus = all > 0 ? (stime / all) * 100 : 0; // system
|
|
497
517
|
}
|
|
518
|
+
// normalized against all cores, so 100 is the ceiling for cpuu + cpus
|
|
519
|
+
const clamped = clampCpuPair(cpuu, cpus);
|
|
498
520
|
return {
|
|
499
521
|
pid: pid,
|
|
500
522
|
utime: utime,
|
|
501
523
|
stime: stime,
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
cpuu: cpuu,
|
|
505
|
-
cpus: cpus
|
|
524
|
+
cpuu: clamped.cpuu,
|
|
525
|
+
cpus: clamped.cpus
|
|
506
526
|
};
|
|
507
527
|
} else {
|
|
508
528
|
return {
|
|
509
529
|
pid: 0,
|
|
510
530
|
utime: 0,
|
|
511
531
|
stime: 0,
|
|
512
|
-
cutime: 0,
|
|
513
|
-
cstime: 0,
|
|
514
532
|
cpuu: 0,
|
|
515
533
|
cpus: 0
|
|
516
534
|
};
|
|
@@ -520,8 +538,6 @@ function calcProcStatLinux(line, all, _cpu_old) {
|
|
|
520
538
|
pid: 0,
|
|
521
539
|
utime: 0,
|
|
522
540
|
stime: 0,
|
|
523
|
-
cutime: 0,
|
|
524
|
-
cstime: 0,
|
|
525
541
|
cpuu: 0,
|
|
526
542
|
cpus: 0
|
|
527
543
|
};
|
|
@@ -533,18 +549,21 @@ function calcProcStatWin(procStat, all, _cpu_old) {
|
|
|
533
549
|
let cpuu = 0;
|
|
534
550
|
let cpus = 0;
|
|
535
551
|
if (_cpu_old.all > 0 && _cpu_old.list[procStat.pid]) {
|
|
536
|
-
|
|
537
|
-
|
|
552
|
+
const delta = all - _cpu_old.all;
|
|
553
|
+
cpuu = delta > 0 ? ((procStat.utime - _cpu_old.list[procStat.pid].utime) / delta) * 100 : 0; // user
|
|
554
|
+
cpus = delta > 0 ? ((procStat.stime - _cpu_old.list[procStat.pid].stime) / delta) * 100 : 0; // system
|
|
538
555
|
} else {
|
|
539
|
-
cpuu = (procStat.utime / all) * 100; // user
|
|
540
|
-
cpus = (procStat.stime / all) * 100; // system
|
|
556
|
+
cpuu = all > 0 ? (procStat.utime / all) * 100 : 0; // user
|
|
557
|
+
cpus = all > 0 ? (procStat.stime / all) * 100 : 0; // system
|
|
541
558
|
}
|
|
559
|
+
// same ceiling as the linux path - cpuu + cpus stays inside [0, 100] (#1007)
|
|
560
|
+
const clamped = clampCpuPair(cpuu, cpus);
|
|
542
561
|
return {
|
|
543
562
|
pid: procStat.pid,
|
|
544
563
|
utime: procStat.utime,
|
|
545
564
|
stime: procStat.stime,
|
|
546
|
-
cpuu: cpuu
|
|
547
|
-
cpus: cpus
|
|
565
|
+
cpuu: clamped.cpuu,
|
|
566
|
+
cpus: clamped.cpus
|
|
548
567
|
};
|
|
549
568
|
}
|
|
550
569
|
|
|
@@ -637,6 +656,11 @@ function processes(callback) {
|
|
|
637
656
|
let command = '';
|
|
638
657
|
let params = '';
|
|
639
658
|
let fullcommand = line.substring(parsedhead[12].from + offset, parsedhead[12].to + offset2).trim();
|
|
659
|
+
// zombies are printed as "[name] <defunct>" - drop the marker so the bracket handling below
|
|
660
|
+
// sees a plain "[name]" and does not leak "] <defunct>" into command and name
|
|
661
|
+
if (fullcommand.endsWith(' <defunct>')) {
|
|
662
|
+
fullcommand = fullcommand.slice(0, -10).trim();
|
|
663
|
+
}
|
|
640
664
|
if (fullcommand.substr(fullcommand.length - 1) === ']') {
|
|
641
665
|
fullcommand = fullcommand.slice(0, -1);
|
|
642
666
|
}
|
|
@@ -855,6 +879,9 @@ function processes(callback) {
|
|
|
855
879
|
result.list.forEach((element) => {
|
|
856
880
|
cmd += ';cat /proc/' + element.pid + '/stat';
|
|
857
881
|
});
|
|
882
|
+
// freeze the baseline before the async call - a concurrent call overwrites _processes_cpu
|
|
883
|
+
// and would leave this one dividing by a few jiffies (#1007)
|
|
884
|
+
const cpuBaseline = Object.assign({}, _processes_cpu);
|
|
858
885
|
exec(cmd, { maxBuffer: 1024 * 102400 }, (error, stdout) => {
|
|
859
886
|
let curr_processes = stdout.toString().split('\n');
|
|
860
887
|
|
|
@@ -865,7 +892,7 @@ function processes(callback) {
|
|
|
865
892
|
let list_new = {};
|
|
866
893
|
let resultProcess = {};
|
|
867
894
|
curr_processes.forEach((element) => {
|
|
868
|
-
resultProcess = calcProcStatLinux(element, all,
|
|
895
|
+
resultProcess = calcProcStatLinux(element, all, cpuBaseline);
|
|
869
896
|
|
|
870
897
|
if (resultProcess.pid) {
|
|
871
898
|
// store pcpu in outer array
|
|
@@ -885,9 +912,7 @@ function processes(callback) {
|
|
|
885
912
|
cpuu: resultProcess.cpuu,
|
|
886
913
|
cpus: resultProcess.cpus,
|
|
887
914
|
utime: resultProcess.utime,
|
|
888
|
-
stime: resultProcess.stime
|
|
889
|
-
cutime: resultProcess.cutime,
|
|
890
|
-
cstime: resultProcess.cstime
|
|
915
|
+
stime: resultProcess.stime
|
|
891
916
|
};
|
|
892
917
|
}
|
|
893
918
|
});
|
|
@@ -950,6 +975,9 @@ function processes(callback) {
|
|
|
950
975
|
}
|
|
951
976
|
} else if (_windows) {
|
|
952
977
|
try {
|
|
978
|
+
// freeze the baseline before the async call - a concurrent call overwrites _processes_cpu
|
|
979
|
+
// and would leave this one with a non positive delta (#1007)
|
|
980
|
+
const cpuBaseline = Object.assign({}, _processes_cpu);
|
|
953
981
|
util
|
|
954
982
|
.powerShell(
|
|
955
983
|
`Get-CimInstance Win32_Process | select-Object ProcessId,ParentProcessId,ExecutionState,Caption,CommandLine,ExecutablePath,UserModeTime,KernelModeTime,WorkingSetSize,Priority,PageFileUsage,
|
|
@@ -960,8 +988,10 @@ function processes(callback) {
|
|
|
960
988
|
const procs = [];
|
|
961
989
|
const procStats = [];
|
|
962
990
|
const list_new = {};
|
|
963
|
-
|
|
964
|
-
|
|
991
|
+
// accumulate from the previous totals and add deltas only - a process that exited
|
|
992
|
+
// must not lower the total, otherwise the denominator turns negative (#559)
|
|
993
|
+
let allcpuu = cpuBaseline.all_utime;
|
|
994
|
+
let allcpus = cpuBaseline.all_stime;
|
|
965
995
|
let processArray = [];
|
|
966
996
|
try {
|
|
967
997
|
stdout = stdout.trim().replace(/^\uFEFF/, '');
|
|
@@ -981,8 +1011,9 @@ function processes(callback) {
|
|
|
981
1011
|
const utime = element.UserModeTime;
|
|
982
1012
|
const stime = element.KernelModeTime;
|
|
983
1013
|
const memw = element.WorkingSetSize;
|
|
984
|
-
|
|
985
|
-
|
|
1014
|
+
const cpuOld = cpuBaseline.list[pid];
|
|
1015
|
+
allcpuu += utime - (cpuOld ? cpuOld.utime : 0);
|
|
1016
|
+
allcpus += stime - (cpuOld ? cpuOld.stime : 0);
|
|
986
1017
|
result.all++;
|
|
987
1018
|
if (!statusValue) {
|
|
988
1019
|
result.unknown++;
|
|
@@ -1027,7 +1058,7 @@ function processes(callback) {
|
|
|
1027
1058
|
result.sleeping = result.all - result.running - result.blocked - result.unknown;
|
|
1028
1059
|
result.list = procs;
|
|
1029
1060
|
procStats.forEach((element) => {
|
|
1030
|
-
let resultProcess = calcProcStatWin(element, allcpuu + allcpus,
|
|
1061
|
+
let resultProcess = calcProcStatWin(element, allcpuu + allcpus, cpuBaseline);
|
|
1031
1062
|
|
|
1032
1063
|
// store pcpu in outer array
|
|
1033
1064
|
let listPos = result.list.map((e) => e.pid).indexOf(resultProcess.pid);
|
|
@@ -1150,12 +1181,16 @@ function processLoad(proc, callback) {
|
|
|
1150
1181
|
if (procSanitized && processes.length && processes[0] !== '------') {
|
|
1151
1182
|
if (_windows) {
|
|
1152
1183
|
try {
|
|
1184
|
+
// freeze the baseline before the async call - a concurrent call overwrites _process_cpu
|
|
1185
|
+
// and would leave this one with a non positive delta (#1007)
|
|
1186
|
+
const cpuBaseline = Object.assign({}, _process_cpu);
|
|
1153
1187
|
util.powerShell('Get-CimInstance Win32_Process | select ProcessId,Caption,UserModeTime,KernelModeTime,WorkingSetSize | ConvertTo-Json -compress').then((stdout, error) => {
|
|
1154
1188
|
if (!error) {
|
|
1155
1189
|
const procStats = [];
|
|
1156
1190
|
const list_new = {};
|
|
1157
|
-
|
|
1158
|
-
let
|
|
1191
|
+
// see processes() - never lower the total when a process exits (#559)
|
|
1192
|
+
let allcpuu = cpuBaseline.all_utime;
|
|
1193
|
+
let allcpus = cpuBaseline.all_stime;
|
|
1159
1194
|
let processArray = [];
|
|
1160
1195
|
try {
|
|
1161
1196
|
stdout = stdout.trim().replace(/^\uFEFF/, '');
|
|
@@ -1172,8 +1207,9 @@ function processLoad(proc, callback) {
|
|
|
1172
1207
|
const utime = element.UserModeTime;
|
|
1173
1208
|
const stime = element.KernelModeTime;
|
|
1174
1209
|
const mem = element.WorkingSetSize;
|
|
1175
|
-
|
|
1176
|
-
|
|
1210
|
+
const cpuOld = cpuBaseline.list[pid];
|
|
1211
|
+
allcpuu += utime - (cpuOld ? cpuOld.utime : 0);
|
|
1212
|
+
allcpus += stime - (cpuOld ? cpuOld.stime : 0);
|
|
1177
1213
|
|
|
1178
1214
|
procStats.push({
|
|
1179
1215
|
pid: pid,
|
|
@@ -1231,7 +1267,7 @@ function processLoad(proc, callback) {
|
|
|
1231
1267
|
|
|
1232
1268
|
// calculate proc stats for each proc
|
|
1233
1269
|
procStats.forEach((element) => {
|
|
1234
|
-
let resultProcess = calcProcStatWin(element, allcpuu + allcpus,
|
|
1270
|
+
let resultProcess = calcProcStatWin(element, allcpuu + allcpus, cpuBaseline);
|
|
1235
1271
|
|
|
1236
1272
|
let listPos = -1;
|
|
1237
1273
|
for (let j = 0; j < result.length; j++) {
|
|
@@ -1377,6 +1413,9 @@ function processLoad(proc, callback) {
|
|
|
1377
1413
|
cmd += ';cat /proc/' + result[i].pids[j] + '/stat';
|
|
1378
1414
|
}
|
|
1379
1415
|
}
|
|
1416
|
+
// freeze the baseline before the async call - a concurrent call overwrites _process_cpu
|
|
1417
|
+
// and would leave this one dividing by a few jiffies (#1007)
|
|
1418
|
+
const cpuBaseline = Object.assign({}, _process_cpu);
|
|
1380
1419
|
exec(cmd, { maxBuffer: 1024 * 102400 }, (error, stdout) => {
|
|
1381
1420
|
let curr_processes = stdout.toString().split('\n');
|
|
1382
1421
|
|
|
@@ -1387,7 +1426,7 @@ function processLoad(proc, callback) {
|
|
|
1387
1426
|
let list_new = {};
|
|
1388
1427
|
let resultProcess = {};
|
|
1389
1428
|
curr_processes.forEach((element) => {
|
|
1390
|
-
resultProcess = calcProcStatLinux(element, all,
|
|
1429
|
+
resultProcess = calcProcStatLinux(element, all, cpuBaseline);
|
|
1391
1430
|
|
|
1392
1431
|
if (resultProcess.pid) {
|
|
1393
1432
|
// find result item
|
|
@@ -1407,9 +1446,7 @@ function processLoad(proc, callback) {
|
|
|
1407
1446
|
cpuu: resultProcess.cpuu,
|
|
1408
1447
|
cpus: resultProcess.cpus,
|
|
1409
1448
|
utime: resultProcess.utime,
|
|
1410
|
-
stime: resultProcess.stime
|
|
1411
|
-
cutime: resultProcess.cutime,
|
|
1412
|
-
cstime: resultProcess.cstime
|
|
1449
|
+
stime: resultProcess.stime
|
|
1413
1450
|
};
|
|
1414
1451
|
}
|
|
1415
1452
|
});
|
package/lib/wifi.js
CHANGED
|
@@ -193,7 +193,7 @@ function ifaceListLinux() {
|
|
|
193
193
|
}
|
|
194
194
|
|
|
195
195
|
function nmiDeviceLinux(iface) {
|
|
196
|
-
const cmd = `nmcli -t -f general,wifi-properties,capabilities,ip4,ip6 device show ${iface} 2> /dev/null`;
|
|
196
|
+
const cmd = `nmcli -t -f general,wifi-properties,capabilities,ip4,ip6 device show ${util.sanitizeString(iface, true)} 2> /dev/null`;
|
|
197
197
|
try {
|
|
198
198
|
const lines = execSync(cmd, util.execOptsLinux).toString().split('\n');
|
|
199
199
|
const ssid = util.getValue(lines, 'GENERAL.CONNECTION');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@depup/systeminformation",
|
|
3
|
-
"version": "5.33.
|
|
3
|
+
"version": "5.33.10-depup.0",
|
|
4
4
|
"description": "Advanced, lightweight system and OS information library (with updated dependencies)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Sebastian Hildebrandt <hildebrandt@plus-innovations.com> (https://plus-innovations.com)",
|
|
@@ -111,8 +111,8 @@
|
|
|
111
111
|
"changes": {},
|
|
112
112
|
"depsUpdated": 0,
|
|
113
113
|
"originalPackage": "systeminformation",
|
|
114
|
-
"originalVersion": "5.33.
|
|
115
|
-
"processedAt": "2026-
|
|
114
|
+
"originalVersion": "5.33.10",
|
|
115
|
+
"processedAt": "2026-09-13T01:00:18.796Z",
|
|
116
116
|
"smokeTest": "passed"
|
|
117
117
|
}
|
|
118
118
|
}
|