diff --git a/CHANGELOG.md b/CHANGELOG.md index a115abd..20c8118 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -98,6 +98,7 @@ Other changes | Version | Date | Comment | | -------------- | -------------- | -------- | +| 3.28.0 | 2017-09-14 | extended windows support `processes()` | | 3.27.1 | 2017-09-13 | updated Raspberry version detection `system()` (Pi 3, Zero) | | 3.27.0 | 2017-09-12 | added raw data to `currentLoad()`, fixed `networkInterfaces()` MAC problem node 8.x | | 3.26.2 | 2017-09-01 | removed redundant code | diff --git a/README.md b/README.md index e403df8..0bb1238 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,7 @@ async function cpu() { ## News and Changes ### Latest Activity +- Version 3.28.0: extended windows support `processes()` - Version 3.27.0: added raw data to `currentLoad()`, fixed `networkInterfaces()` MAC problem node 8.x - Version 3.26.0: improved windows support `getDynamicData()`, updated docs - Version 3.25.0: improved windows support `networkStats()`, `cpuCache()`, bug fix `getStaticData()` @@ -329,26 +330,28 @@ I also created a nice little command line tool called [mmon][mmon-github-url] ( | | raw_currentload... | X | X | X | CPU-Load raw values (ticks) | | | cpus[] | X | X | X | current loads per CPU in % + raw ticks | | si.fullLoad(cb) | : integer | X | X | X | CPU-full load since bootup in % | -| si.processes(cb) | {...} | X | X | | # running processes | -| | all | X | X | | # of all processes | -| | running | X | X | | # of all processes running | -| | blocked | X | X | | # of all processes blocked | -| | sleeping | X | X | | # of all processes sleeping | -| | list[] | X | X | | list of all processes incl. details | -| | ...[0].pid | X | X | | process PID | -| | ...[0].pcpu | X | X | | process % CPU usage | -| | ...[0].pcpuu | X | | | process % CPU usage (user) | -| | ...[0].pcpus | X | | | process % CPU usage (system) | -| | ...[0].pmem | X | X | | process memory % | -| | ...[0].priority | X | X | | process priotity | -| | ...[0].mem_vsz | X | X | | process virtual memory size | -| | ...[0].mem_rss | X | X | | process mem resident set size | +| si.processes(cb) | {...} | X | X | X | # running processes | +| | all | X | X | X | # of all processes | +| | running | X | X | X | # of all processes running | +| | blocked | X | X | X | # of all processes blocked | +| | sleeping | X | X | X | # of all processes sleeping | +| | unknown | | | X | # of all processes unknown status | +| | list[] | X | X | X | list of all processes incl. details | +| | ...[0].pid | X | X | X | process PID | +| | ...[0].name | X | X | X | process name | +| | ...[0].pcpu | X | X | X | process % CPU usage | +| | ...[0].pcpuu | X | | X | process % CPU usage (user) | +| | ...[0].pcpus | X | | X | process % CPU usage (system) | +| | ...[0].pmem | X | X | X | process memory % | +| | ...[0].priority | X | X | X | process priotity | +| | ...[0].mem_vsz | X | X | X | process virtual memory size | +| | ...[0].mem_rss | X | X | X | process mem resident set size | | | ...[0].nice | X | X | | process nice value | -| | ...[0].started | X | X | | process start time | -| | ...[0].state | X | X | | process state (e.g. sleeping) | +| | ...[0].started | X | X | X | process start time | +| | ...[0].state | X | X | X | process state (e.g. sleeping) | | | ...[0].tty | X | X | | tty from which process was started | | | ...[0].user | X | X | | user who started process | -| | ...[0].command | X | X | | process starting command | +| | ...[0].command | X | X | X | process starting command | | si.processLoad('apache2',cb) | {...} | X | X | | detailed information about given process | | | proc | X | X | | process name | | | pid | X | X | | PID | diff --git a/lib/battery.js b/lib/battery.js index 388c6c8..86ee9dc 100644 --- a/lib/battery.js +++ b/lib/battery.js @@ -24,20 +24,6 @@ const _darwin = (_platform === 'Darwin'); const _windows = (_platform === 'Windows_NT'); const NOT_SUPPORTED = 'not supported'; -function getValue(lines, property, separator) { - separator = separator || ':'; - property = property.toLowerCase(); - for (let i = 0; i < lines.length; i++) { - if (lines[i].toLowerCase().startsWith(property)) { - const parts = lines[i].split(separator); - if (parts.length > 1) { - return parts[1].trim(); - } - } - } - return ''; -} - module.exports = function (callback) { return new Promise((resolve, reject) => { @@ -119,12 +105,12 @@ module.exports = function (callback) { exec("WMIC Path Win32_Battery Get BatteryStatus, DesignCapacity, EstimatedChargeRemaining /value", function (error, stdout) { if (stdout) { let lines = stdout.split('\r\n'); - let status = getValue(lines, 'BatteryStatus', '=').trim(); + let status = util.getValue(lines, 'BatteryStatus', '=').trim(); if (status) { status = parseInt(status || '2'); result.hasbattery = true; - result.maxcapacity = parseInt(getValue(lines, 'DesignCapacity', '=') || 0); - result.percent = parseInt(getValue(lines, 'EstimatedChargeRemaining', '=') || 0); + result.maxcapacity = parseInt(util.getValue(lines, 'DesignCapacity', '=') || 0); + result.percent = parseInt(util.getValue(lines, 'EstimatedChargeRemaining', '=') || 0); result.currentcapacity = parseInt(result.maxcapacity * result.percent / 100); result.ischarging = (status >= 6 && status <= 9) || (!(status === 3) && !(status === 1) && result.percent < 100); } diff --git a/lib/cpu.js b/lib/cpu.js index a6c5ef3..c4d0d9d 100644 --- a/lib/cpu.js +++ b/lib/cpu.js @@ -63,20 +63,6 @@ function cpuBrandManufacturer(res) { return res; } -function getValue(lines, property, separator) { - separator = separator || ':'; - property = property.toLowerCase(); - for (let i = 0; i < lines.length; i++) { - if (lines[i].toLowerCase().startsWith(property)) { - const parts = lines[i].split(separator); - if (parts.length > 1) { - return parts[1].trim(); - } - } - } - return ''; -} - // -------------------------- // CPU - brand, speed @@ -103,18 +89,18 @@ function getCpu() { exec("sysctl machdep.cpu hw.cpufrequency_max hw.cpufrequency_min", function (error, stdout) { if (!error) { let lines = stdout.toString().split('\n'); - const modelline = getValue(lines, 'machdep.cpu.brand_string'); + const modelline = util.getValue(lines, 'machdep.cpu.brand_string'); result.brand = modelline.split('@')[0].trim(); result.speed = modelline.split('@')[1].trim(); result.speed = parseFloat(result.speed.replace(/GHz+/g, "")).toFixed(2); _cpu_speed = result.speed; result = cpuBrandManufacturer(result); - result.speedmin = (getValue(lines, 'hw.cpufrequency_min') / 1000000000.0 ).toFixed(2); - result.speedmax = (getValue(lines, 'hw.cpufrequency_max') / 1000000000.0 ).toFixed(2); - result.vendor = getValue(lines, 'machdep.cpu.vendor'); - result.family = getValue(lines, 'machdep.cpu.family'); - result.model = getValue(lines, 'machdep.cpu.model'); - result.stepping = getValue(lines, 'machdep.cpu.stepping'); + result.speedmin = (util.getValue(lines, 'hw.cpufrequency_min') / 1000000000.0 ).toFixed(2); + result.speedmax = (util.getValue(lines, 'hw.cpufrequency_max') / 1000000000.0 ).toFixed(2); + result.vendor = util.getValue(lines, 'machdep.cpu.vendor'); + result.family = util.getValue(lines, 'machdep.cpu.family'); + result.model = util.getValue(lines, 'machdep.cpu.model'); + result.stepping = util.getValue(lines, 'machdep.cpu.stepping'); } cpuCache().then(res => { @@ -127,7 +113,7 @@ function getCpu() { exec("export LC_ALL=C; lscpu; unset LC_ALL", function (error, stdout) { if (!error) { let lines = stdout.toString().split('\n'); - const modelline = getValue(lines, 'model name'); + const modelline = util.getValue(lines, 'model name'); result.brand = modelline.split('@')[0].trim(); result.speed = modelline.split('@')[1] ? parseFloat(modelline.split('@')[1].trim()).toFixed(2) : '0.00'; if (result.speed === '0.00') { @@ -135,27 +121,27 @@ function getCpu() { if (current !== '0.00') result.speed = current; } _cpu_speed = result.speed; - result.speedmin = Math.round(parseFloat(getValue(lines, 'cpu min mhz').replace(/,/g, '.')) / 10.0) / 100; + result.speedmin = Math.round(parseFloat(util.getValue(lines, 'cpu min mhz').replace(/,/g, '.')) / 10.0) / 100; result.speedmin = result.speedmin ? parseFloat(result.speedmin).toFixed(2) : '' - result.speedmax = Math.round(parseFloat(getValue(lines, 'cpu max mhz').replace(/,/g, '.')) / 10.0) / 100; + result.speedmax = Math.round(parseFloat(util.getValue(lines, 'cpu max mhz').replace(/,/g, '.')) / 10.0) / 100; result.speedmax = result.speedmax ? parseFloat(result.speedmax).toFixed(2) : '' result = cpuBrandManufacturer(result); - result.vendor = getValue(lines, 'vendor id'); - // if (!result.vendor) { result.vendor = getValue(lines, 'anbieterkennung'); } - result.family = getValue(lines, 'cpu family'); - // if (!result.family) { result.family = getValue(lines, 'prozessorfamilie'); } - result.model = getValue(lines, 'model:'); - // if (!result.model) { result.model = getValue(lines, 'modell:'); } - result.stepping = getValue(lines, 'stepping'); - result.revision = getValue(lines, 'cpu revision'); - result.cache.l1d = getValue(lines, 'l1d cache'); + result.vendor = util.getValue(lines, 'vendor id'); + // if (!result.vendor) { result.vendor = util.getValue(lines, 'anbieterkennung'); } + result.family = util.getValue(lines, 'cpu family'); + // if (!result.family) { result.family = util.getValue(lines, 'prozessorfamilie'); } + result.model = util.getValue(lines, 'model:'); + // if (!result.model) { result.model = util.getValue(lines, 'modell:'); } + result.stepping = util.getValue(lines, 'stepping'); + result.revision = util.getValue(lines, 'cpu revision'); + result.cache.l1d = util.getValue(lines, 'l1d cache'); if (result.cache.l1d) { result.cache.l1d = parseInt(result.cache.l1d) * (result.cache.l1d.indexOf('K') !== -1 ? 1024 : 1)} - result.cache.l1i = getValue(lines, 'l1i cache'); + result.cache.l1i = util.getValue(lines, 'l1i cache'); if (result.cache.l1i) { result.cache.l1i = parseInt(result.cache.l1i) * (result.cache.l1i.indexOf('K') !== -1 ? 1024 : 1)} - result.cache.l2 = getValue(lines, 'l2 cache'); + result.cache.l2 = util.getValue(lines, 'l2 cache'); if (result.cache.l2) { result.cache.l2 = parseInt(result.cache.l2) * (result.cache.l2.indexOf('K') !== -1 ? 1024 : 1)} - result.cache.l3 = getValue(lines, 'l3 cache'); + result.cache.l3 = util.getValue(lines, 'l3 cache'); if (result.cache.l3) { result.cache.l3 = parseInt(result.cache.l3) * (result.cache.l3.indexOf('K') !== -1 ? 1024 : 1)} } else { @@ -167,7 +153,7 @@ function getCpu() { exec("wmic cpu get name, description, revision, l2cachesize, l3cachesize, manufacturer, currentclockspeed, maxclockspeed /value", function (error, stdout) { if (!error) { let lines = stdout.split('\r\n'); - let name = getValue(lines, 'name', '=') || ''; + let name = util.getValue(lines, 'name', '=') || ''; if (name.indexOf('@') >= 0) { result.brand = name.split('@')[0].trim(); result.speed = name.split('@')[1].trim(); @@ -178,21 +164,21 @@ function getCpu() { result.speed = 0; } result = cpuBrandManufacturer(result); - result.revision = getValue(lines, 'revision', '='); + result.revision = util.getValue(lines, 'revision', '='); result.cache.l1d = 0; result.cache.l1i = 0; - result.cache.l2 = getValue(lines, 'l2cachesize', '='); - result.cache.l3 = getValue(lines, 'l3cachesize', '='); + result.cache.l2 = util.getValue(lines, 'l2cachesize', '='); + result.cache.l3 = util.getValue(lines, 'l3cachesize', '='); if (result.cache.l2) { result.cache.l2 = parseInt(result.cache.l2) * 1024} if (result.cache.l3) { result.cache.l3 = parseInt(result.cache.l3) * 1024} - result.vendor = getValue(lines, 'manufacturer', '='); - result.speedmax = Math.round(parseFloat(getValue(lines, 'maxclockspeed', '=').replace(/,/g, '.')) / 10.0) / 100; + result.vendor = util.getValue(lines, 'manufacturer', '='); + result.speedmax = Math.round(parseFloat(util.getValue(lines, 'maxclockspeed', '=').replace(/,/g, '.')) / 10.0) / 100; result.speedmax = result.speedmax ? parseFloat(result.speedmax).toFixed(2) : ''; if (!result.speed) { result.speed = result.speedmax } - let description = getValue(lines, 'description', '=').split(' '); + let description = util.getValue(lines, 'description', '=').split(' '); for (let i = 0; i < description.length; i++) { if (description[i].toLowerCase().startsWith('family') && (i+1) < description.length && description[i+1]) { result.family = description[i+1] @@ -510,8 +496,8 @@ function cpuCache(callback) { let lines = stdout.split('\r\n'); result.l1d = 0; result.l1i = 0; - result.l2 = getValue(lines, 'l2cachesize', '='); - result.l3 = getValue(lines, 'l3cachesize', '='); + result.l2 = util.getValue(lines, 'l2cachesize', '='); + result.l3 = util.getValue(lines, 'l3cachesize', '='); if (result.l2) { result.l2 = parseInt(result.l2) * 1024} if (result.l3) { result.l3 = parseInt(result.l3) * 1024} } diff --git a/lib/docker.js b/lib/docker.js index b89e094..3dcd4c5 100644 --- a/lib/docker.js +++ b/lib/docker.js @@ -14,7 +14,7 @@ const os = require('os'); const util = require('./util'); -const DockerSocket = require('./dockerSocket'); +const DockerSocket = require('./dockerSocket'); let _platform = os.type(); diff --git a/lib/filesystem.js b/lib/filesystem.js index 45bd736..0f5b04e 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -28,27 +28,6 @@ const NOT_SUPPORTED = 'not supported'; let _fs_speed = {}; let _disk_io = {}; -function getValue(lines, property, separator, trimmed) { - separator = separator || ':'; - property = property.toLowerCase(); - for (let i = 0; i < lines.length; i++) { - let line = lines[i].toLowerCase(); - if (trimmed) { - line = line.trim(); - } - if (line.toLowerCase().startsWith(property)) { - const parts = lines[i].split(separator); - if (parts.length >= 2) { - parts.shift(); - return parts.join(':').trim(); - } else { - return '' - } - } - } - return ''; -} - // -------------------------- // FS - mounted file systems @@ -598,18 +577,18 @@ function diskLayout(callback) { devices.forEach(function (device) { let lines = device.split('\n'); let mediumType = ''; - const logical = getValue(lines, 'logical name', ':', true).trim().replace(/\/dev\//g, ''); + const logical = util.getValue(lines, 'logical name', ':', true).trim().replace(/\/dev\//g, ''); try { mediumType = execSync('cat /sys/block/' + logical + '/queue/rotational').toString().split('\n')[0]; } catch (e) { } - const size = getValue(lines, 'size', ':', true).trim(); + const size = util.getValue(lines, 'size', ':', true).trim(); if (size && lines.length > 0 && lines[0].trim() === 'disk') { result.push({ type: (mediumType === '0' ? 'SSD' : (mediumType === '1' ? 'HD' : (device.indexOf('SSD') > -1 ? 'SSD' : 'HD'))), // to be tested ... /sys/block/sda/queue/rotational - name: getValue(lines, 'product:', ':', true), - vendor: getValue(lines, 'vendor:', ':', true), + name: util.getValue(lines, 'product:', ':', true), + vendor: util.getValue(lines, 'vendor:', ':', true), size: parseInt(size.match(/\(([^)]+)\)/)[1]) * 1000 * 1000 * 1000 * 1000, bytesPerSector: -1, totalCylinders: -1, @@ -618,8 +597,8 @@ function diskLayout(callback) { totalTracks: -1, tracksPerCylinder: -1, sectorsPerTrack: -1, - firmwareRevision: getValue(lines, 'version:', ':', true).trim(), - serialNum: getValue(lines, 'serial:', ':', true).trim(), + firmwareRevision: util.getValue(lines, 'version:', ':', true).trim(), + serialNum: util.getValue(lines, 'serial:', ':', true).trim(), interfaceType: '', }) } @@ -639,8 +618,8 @@ function diskLayout(callback) { devices.shift(); devices.forEach(function (device) { let lines = device.split('\n'); - const mediumType = getValue(lines, 'Medium Type', ':', true).trim(); - const sizeStr = getValue(lines, 'capacity', ':', true).trim(); + const mediumType = util.getValue(lines, 'Medium Type', ':', true).trim(); + const sizeStr = util.getValue(lines, 'capacity', ':', true).trim(); if (sizeStr) { let size = parseInt(sizeStr.match(/\(([^)]+)\)/)[1].replace(/\./g, "")); if (!size) { @@ -649,7 +628,7 @@ function diskLayout(callback) { if (size) { result.push({ type: mediumType.startsWith('Solid') ? 'SSD' : 'HD', - name: getValue(lines, 'Model', ':', true).trim(), + name: util.getValue(lines, 'Model', ':', true).trim(), vendor: '', size: size, bytesPerSector: -1, @@ -659,9 +638,9 @@ function diskLayout(callback) { totalTracks: -1, tracksPerCylinder: -1, sectorsPerTrack: -1, - firmwareRevision: getValue(lines, 'Revision', ':', true).trim(), - serialNum: getValue(lines, 'Serial Number', ':', true).trim(), - interfaceType: getValue(lines, 'InterfaceType', ':', true).trim() + firmwareRevision: util.getValue(lines, 'Revision', ':', true).trim(), + serialNum: util.getValue(lines, 'Serial Number', ':', true).trim(), + interfaceType: util.getValue(lines, 'InterfaceType', ':', true).trim() }) } } @@ -680,23 +659,23 @@ function diskLayout(callback) { let devices = stdout.toString().split('\r\n\r\n\r\n'); devices.forEach(function (device) { let lines = device.split('\r\n'); - const size = getValue(lines, 'Size', '=').trim(); + const size = util.getValue(lines, 'Size', '=').trim(); if (size) { result.push({ type: device.indexOf('SSD') > -1 ? 'SSD' : 'HD', // not really correct(!) ... maybe this obe is better: MSFT_PhysicalDisk - Media Type?? - name: getValue(lines, 'Caption', '='), - vendor: getValue(lines, 'Manufacturer', '='), + name: util.getValue(lines, 'Caption', '='), + vendor: util.getValue(lines, 'Manufacturer', '='), size: parseInt(size), - bytesPerSector: parseInt(getValue(lines, 'BytesPerSector', '=')), - totalCylinders: parseInt(getValue(lines, 'TotalCylinders', '=')), - totalHeads: parseInt(getValue(lines, 'TotalHeads', '=')), - totalSectors: parseInt(getValue(lines, 'TotalSectors', '=')), - totalTracks: parseInt(getValue(lines, 'TotalTracks', '=')), - tracksPerCylinder: parseInt(getValue(lines, 'TracksPerCylinder', '=')), - sectorsPerTrack: parseInt(getValue(lines, 'SectorsPerTrack', '=')), - firmwareRevision: getValue(lines, 'FirmwareRevision', '=').trim(), - serialNum: getValue(lines, 'SerialNumber', '=').trim(), - interfaceType: getValue(lines, 'InterfaceType', '=').trim() + bytesPerSector: parseInt(util.getValue(lines, 'BytesPerSector', '=')), + totalCylinders: parseInt(util.getValue(lines, 'TotalCylinders', '=')), + totalHeads: parseInt(util.getValue(lines, 'TotalHeads', '=')), + totalSectors: parseInt(util.getValue(lines, 'TotalSectors', '=')), + totalTracks: parseInt(util.getValue(lines, 'TotalTracks', '=')), + tracksPerCylinder: parseInt(util.getValue(lines, 'TracksPerCylinder', '=')), + sectorsPerTrack: parseInt(util.getValue(lines, 'SectorsPerTrack', '=')), + firmwareRevision: util.getValue(lines, 'FirmwareRevision', '=').trim(), + serialNum: util.getValue(lines, 'SerialNumber', '=').trim(), + interfaceType: util.getValue(lines, 'InterfaceType', '=').trim() }) } }); diff --git a/lib/graphics.js b/lib/graphics.js index 6e33ee3..accd690 100644 --- a/lib/graphics.js +++ b/lib/graphics.js @@ -27,20 +27,6 @@ let _resolutionx = 0; let _resolutiony = 0; let _pixeldepth = 0; -function getValue(lines, property, separator) { - separator = separator || ':'; - property = property.toLowerCase(); - for (let i = 0; i < lines.length; i++) { - if (lines[i].toLowerCase().startsWith(property)) { - const parts = lines[i].split(separator); - if (parts.length > 1) { - return parts[1].trim(); - } - } - } - return ''; -} - function toInt(value) { let result = parseInt(value,10); if (isNaN(result)) { @@ -363,15 +349,15 @@ function graphics(callback) { let lines = sections[i].trim().split('\r\n'); controllers.push({ - model: getValue(lines, 'name', '='), - vendor: getValue(lines, 'AdapterCompatibility', '='), - bus: getValue(lines, 'PNPDeviceID', '=').startsWith('PCI') ? 'PCI' : '', - vram: getValue(lines, 'AdapterRAM', '='), - vramDynamic: (getValue(lines, 'VideoMemoryType', '=') === '2') + model: util.getValue(lines, 'name', '='), + vendor: util.getValue(lines, 'AdapterCompatibility', '='), + bus: util.getValue(lines, 'PNPDeviceID', '=').startsWith('PCI') ? 'PCI' : '', + vram: util.getValue(lines, 'AdapterRAM', '='), + vramDynamic: (util.getValue(lines, 'VideoMemoryType', '=') === '2') }); - _resolutionx = toInt(getValue(lines, 'CurrentHorizontalResolution', '=')); - _resolutiony = toInt(getValue(lines, 'CurrentVerticalResolution', '=')); - _pixeldepth = toInt(getValue(lines, 'CurrentBitsPerPixel', '=')); + _resolutionx = toInt(util.getValue(lines, 'CurrentHorizontalResolution', '=')); + _resolutiony = toInt(util.getValue(lines, 'CurrentVerticalResolution', '=')); + _pixeldepth = toInt(util.getValue(lines, 'CurrentBitsPerPixel', '=')); } } } @@ -385,9 +371,9 @@ function graphics(callback) { if (sections[i].trim() !== "") { let lines = sections[i].trim().split('\r\n'); displays.push({ - model: getValue(lines, 'MonitorManufacturer', '='), - resolutionx: toInt(getValue(lines, 'ScreenWidth', '=')), - resolutiony: toInt(getValue(lines, 'ScreenHeight', '=')), + model: util.getValue(lines, 'MonitorManufacturer', '='), + resolutionx: toInt(util.getValue(lines, 'ScreenWidth', '=')), + resolutiony: toInt(util.getValue(lines, 'ScreenHeight', '=')), }); } } diff --git a/lib/memory.js b/lib/memory.js index f6131e5..d3f6552 100644 --- a/lib/memory.js +++ b/lib/memory.js @@ -24,26 +24,6 @@ const _darwin = (_platform === 'Darwin'); const _windows = (_platform === 'Windows_NT'); const NOT_SUPPORTED = 'not supported'; -function getValue(lines, property, separator, trimmed) { - separator = separator || ':'; - property = property.toLowerCase(); - for (let i = 0; i < lines.length; i++) { - let line = lines[i].toLowerCase(); - if (trimmed) { - line = line.trim(); - } - if (line.toLowerCase().startsWith(property)) { - const parts = lines[i].split(separator); - if (parts.length >= 2) { - parts.shift(); - return parts.join(':').trim(); - } else { - return '' - } - } - } - return ''; -} // _______________________________________________________________________________________ // | R A M | H D | // |______________________|_________________________| | | @@ -213,16 +193,16 @@ function memLayout(callback) { devices.forEach(function (device) { let lines = device.split('\n'); result.push({ - size: parseInt(getValue(lines, ' Size'))*1024*1024, - bank: getValue(lines, ' Bank Locator'), - type: getValue(lines, ' Type:'), - clockSpeed: (getValue(lines, ' Configured Clock Speed:') ? parseInt(getValue(lines, ' Configured Clock Speed:')) : parseInt(getValue(lines, ' Speed:'))), - formFactor: getValue(lines, ' Form Factor:'), + size: parseInt(util.getValue(lines, ' Size'))*1024*1024, + bank: util.getValue(lines, ' Bank Locator'), + type: util.getValue(lines, ' Type:'), + clockSpeed: (util.getValue(lines, ' Configured Clock Speed:') ? parseInt(util.getValue(lines, ' Configured Clock Speed:')) : parseInt(util.getValue(lines, ' Speed:'))), + formFactor: util.getValue(lines, ' Form Factor:'), partNum: '', - serialNum: getValue(lines, ' Serial Number:'), - voltageConfigured: parseFloat(getValue(lines, ' Configured Voltage:')), - voltageMin: parseFloat(getValue(lines, ' Minimum Voltage:')), - voltageMax: parseFloat(getValue(lines, ' Maximum Voltage:')), + serialNum: util.getValue(lines, ' Serial Number:'), + voltageConfigured: parseFloat(util.getValue(lines, ' Configured Voltage:')), + voltageMin: parseFloat(util.getValue(lines, ' Minimum Voltage:')), + voltageMax: parseFloat(util.getValue(lines, ' Maximum Voltage:')), }) }); } @@ -238,16 +218,16 @@ function memLayout(callback) { devices.shift(); devices.forEach(function (device) { let lines = device.split('\n'); - const size = parseInt(getValue(lines, ' Size')); + const size = parseInt(util.getValue(lines, ' Size')); if (size) { result.push({ size: size * 1024 * 1024 * 1024, bank: '', - type: getValue(lines, ' Type:'), - clockSpeed: parseInt(getValue(lines, ' Speed:')), + type: util.getValue(lines, ' Type:'), + clockSpeed: parseInt(util.getValue(lines, ' Speed:')), formFactor: '', - partNum: getValue(lines, ' Part Number:'), - serialNum: getValue(lines, ' Serial Number:'), + partNum: util.getValue(lines, ' Part Number:'), + serialNum: util.getValue(lines, ' Serial Number:'), voltageConfigured: -1, voltageMin: -1, voltageMax: -1, @@ -270,16 +250,16 @@ function memLayout(callback) { devices.forEach(function (device) { let lines = device.split('\r\n'); result.push({ - size: parseInt(getValue(lines, 'Capacity', '=')), - bank: getValue(lines, 'abel', '='), // BankLabel - type: memoryTypes[parseInt(getValue(lines, 'MemoryType', '='))], - clockSpeed: parseInt(getValue(lines, 'ConfiguredClockSpeed', '=')), - formFactor: FormFactors[parseInt(getValue(lines, 'FormFactor', '='))], - partNum: getValue(lines, 'PartNumber', '='), - serialNum: getValue(lines, 'SerialNumber', '='), - voltageConfigured: parseInt(getValue(lines, 'ConfiguredVoltage', '=')) / 1000.0, - voltageMin: parseInt(getValue(lines, 'MinVoltage', '=')) / 1000.0, - voltageMax: parseInt(getValue(lines, 'MaxVoltage', '=')) / 1000.0, + size: parseInt(util.getValue(lines, 'Capacity', '=')), + bank: util.getValue(lines, 'abel', '='), // BankLabel + type: memoryTypes[parseInt(util.getValue(lines, 'MemoryType', '='))], + clockSpeed: parseInt(util.getValue(lines, 'ConfiguredClockSpeed', '=')), + formFactor: FormFactors[parseInt(util.getValue(lines, 'FormFactor', '='))], + partNum: util.getValue(lines, 'PartNumber', '='), + serialNum: util.getValue(lines, 'SerialNumber', '='), + voltageConfigured: parseInt(util.getValue(lines, 'ConfiguredVoltage', '=')) / 1000.0, + voltageMin: parseInt(util.getValue(lines, 'MinVoltage', '=')) / 1000.0, + voltageMax: parseInt(util.getValue(lines, 'MaxVoltage', '=')) / 1000.0, }) }); } diff --git a/lib/network.js b/lib/network.js index 46d34dc..d5f23ea 100644 --- a/lib/network.js +++ b/lib/network.js @@ -29,20 +29,6 @@ let _network = {}; let _default_iface; let _mac = {}; -function getValue(lines, property, separator) { - separator = separator || ':'; - property = property.toLowerCase(); - for (let i = 0; i < lines.length; i++) { - if (lines[i].toLowerCase().startsWith(property)) { - const parts = lines[i].split(separator); - if (parts.length > 1) { - return parts[1].trim(); - } - } - } - return ''; -} - function getDefaultNetworkInterface() { if (!_default_iface) { @@ -225,11 +211,11 @@ function networkStats(iface, callback) { if (sections[i].trim() !== "") { let lines = sections[i].trim().split('\r\n'); - let netEnabled = getValue(lines, 'NetEnabled', '='); + let netEnabled = util.getValue(lines, 'NetEnabled', '='); if (netEnabled) { nics.push({ - mac: getValue(lines, 'MACAddress', '=').toLowerCase(), - name: getValue(lines, 'Name', '=').replace(/[()\[\] ]+/g, "").toLowerCase(), + mac: util.getValue(lines, 'MACAddress', '=').toLowerCase(), + name: util.getValue(lines, 'Name', '=').replace(/[()\[\] ]+/g, "").toLowerCase(), netEnabled: netEnabled === 'TRUE' }); } @@ -247,9 +233,9 @@ function networkStats(iface, callback) { let lines = sections[i].trim().split('\r\n'); perfData.push({ - name: getValue(lines, 'Name', '=').replace(/[()\[\] ]+/g, "").toLowerCase(), - rx: parseInt(getValue(lines, 'BytesReceivedPersec', '='),10), - tx: parseInt(getValue(lines, 'BytesSentPersec', '='),10) + name: util.getValue(lines, 'Name', '=').replace(/[()\[\] ]+/g, "").toLowerCase(), + rx: parseInt(util.getValue(lines, 'BytesReceivedPersec', '='),10), + tx: parseInt(util.getValue(lines, 'BytesSentPersec', '='),10) }); } } diff --git a/lib/processes.js b/lib/processes.js index 81bb527..40f54e7 100644 --- a/lib/processes.js +++ b/lib/processes.js @@ -31,6 +31,30 @@ let _process_cpu = { result: {} }; +let _winStatusValues = { + '0': 'unknown', + '1': 'other', + '2': 'ready', + '3': 'running', + '4': 'blocked', + '5': 'suspended blocked', + '6': 'suspended ready', + '7': 'terminated', + '8': 'stopped', + '9': 'growing', +} + + +function parseTimeWin(time) { + time = time || ''; + if (time) { + return (time.substr(0,4) + '-' + time.substr(4,2) + '-' + time.substr(6,2) + ' ' + time.substr(8,2) + ':' + time.substr(10,2) + ':' + time.substr(12,2)) + } else { + return ''; + } + +} + // -------------------------- // PS - services // pass a comma separated string with services to check (mysql, apache, postgresql, ...) @@ -152,6 +176,19 @@ function processes(callback) { } + function getName(command) { + command = command || ''; + let result = command.split(' '); + if (result.substr(-1) === ':') { + result = result.substr(0, result.length - 1); + } + if (result.substr(0,1) !== '[') { + let parts = part.split('/'); + result = parts[parts.length]; + } + return result + } + function parseLine(line) { let offset = 0; let offset2 = 0; @@ -193,6 +230,7 @@ function processes(callback) { return ({ pid: pid, + name: _linux ? getName(command) : command, pcpu: pcpu, pcpuu: 0, pcpus: 0, @@ -293,94 +331,198 @@ function processes(callback) { } } + function calcProcPidStat(procStat, all) { + // calc + let pcpuu = 0; + let pcpus = 0; + if (_process_cpu.all > 0 && _process_cpu.list[procStat.pid]) { + pcpuu = (procStat.utime - _process_cpu.list[procStat.pid].utime) / (all - _process_cpu.all) * 100; // user + pcpus = (procStat.stime - _process_cpu.list[procStat.pid].stime) / (all - _process_cpu.all) * 100; // system + } else { + pcpuu = (procStat.utime) / (all) * 100; // user + pcpus = (procStat.stime) / (all) * 100; // system + } + return { + pid: procStat.pid, + utime: procStat.utime, + stime: procStat.stime, + pcpuu: pcpuu, + pcpus: pcpus + } + } + return new Promise((resolve, reject) => { process.nextTick(() => { - if (_windows) { - let error = new Error(NOT_SUPPORTED); - if (callback) { callback(NOT_SUPPORTED) } - reject(error); - } let result = { all: 0, running: 0, blocked: 0, sleeping: 0, + unknown: 0, list: [] }; let cmd = ""; if ((_process_cpu.ms && Date.now() - _process_cpu.ms >= 500) || _process_cpu.ms === 0) { - if (_linux) cmd = "ps axo pid:10,pcpu:6,pmem:6,pri:5,vsz:10,rss:10,ni:5,start:20,state:20,tty:20,user:20,command"; - if (_darwin) cmd = "ps acxo pid,pcpu,pmem,pri,vsz,rss,nice,start,state,tty,user,command -r"; - exec(cmd, function (error, stdout) { - if (!error) { - result.list = parseProcesses(stdout.toString().split('\n')); - result.all = result.list.length; - result.running = result.list.filter(function (e) { - return e.state === 'running' - }).length; - result.blocked = result.list.filter(function (e) { - return e.state === 'blocked' - }).length; - result.sleeping = result.list.filter(function (e) { - return e.state === 'sleeping' - }).length; + if (_linux || _darwin) { + if (_linux) cmd = "ps axo pid:10,pcpu:6,pmem:6,pri:5,vsz:10,rss:10,ni:5,start:20,state:20,tty:20,user:20,command"; + if (_darwin) cmd = "ps acxo pid,pcpu,pmem,pri,vsz,rss,nice,start,state,tty,user,command -r"; + exec(cmd, function (error, stdout) { + if (!error) { + result.list = parseProcesses(stdout.toString().split('\n')); + result.all = result.list.length; + result.running = result.list.filter(function (e) { + return e.state === 'running' + }).length; + result.blocked = result.list.filter(function (e) { + return e.state === 'blocked' + }).length; + result.sleeping = result.list.filter(function (e) { + return e.state === 'sleeping' + }).length; - if (_linux) { - // calc process_cpu - ps is not accurate in linux! - cmd = "cat /proc/stat | grep 'cpu '"; - for (let i = 0; i < result.list.length; i++) { - cmd += (';cat /proc/' + result.list[i].pid + '/stat') - } - exec(cmd, function (error, stdout) { - let curr_processes = stdout.toString().split('\n'); + if (_linux) { + // calc process_cpu - ps is not accurate in linux! + cmd = "cat /proc/stat | grep 'cpu '"; + for (let i = 0; i < result.list.length; i++) { + cmd += (';cat /proc/' + result.list[i].pid + '/stat') + } + exec(cmd, function (error, stdout) { + let curr_processes = stdout.toString().split('\n'); - // first line (all - /proc/stat) - let all = parseProcStat(curr_processes.shift()); + // first line (all - /proc/stat) + let all = parseProcStat(curr_processes.shift()); - // process - let list_new = {}; - let resultProcess = {}; - for (let i = 0; i < curr_processes.length; i++) { - resultProcess = parseProcPidStat(curr_processes[i], all); + // process + let list_new = {}; + let resultProcess = {}; + for (let i = 0; i < curr_processes.length; i++) { + resultProcess = parseProcPidStat(curr_processes[i], all); - if (resultProcess.pid) { + if (resultProcess.pid) { - // store pcpu in outer array - let listPos = result.list.map(function (e) { return e.pid; }).indexOf(resultProcess.pid); - if (listPos >= 0) { - result.list[listPos].pcpu = resultProcess.pcpuu + resultProcess.pcpus; - result.list[listPos].pcpuu = resultProcess.pcpuu; - result.list[listPos].pcpus = resultProcess.pcpus; - } + // store pcpu in outer array + let listPos = result.list.map(function (e) { return e.pid; }).indexOf(resultProcess.pid); + if (listPos >= 0) { + result.list[listPos].pcpu = resultProcess.pcpuu + resultProcess.pcpus; + result.list[listPos].pcpuu = resultProcess.pcpuu; + result.list[listPos].pcpus = resultProcess.pcpus; + } - // save new values - list_new[resultProcess.pid] = { - pcpuu: resultProcess.pcpuu, - pcpus: resultProcess.pcpus, - utime: resultProcess.utime, - stime: resultProcess.stime, - cutime: resultProcess.cutime, - cstime: resultProcess.cstime + // save new values + list_new[resultProcess.pid] = { + pcpuu: resultProcess.pcpuu, + pcpus: resultProcess.pcpus, + utime: resultProcess.utime, + stime: resultProcess.stime, + cutime: resultProcess.cutime, + cstime: resultProcess.cstime + } } } - } - // store old values - _process_cpu.all = all; - _process_cpu.list = list_new; - _process_cpu.ms = Date.now() - _process_cpu.ms; - _process_cpu.result = result; + // store old values + _process_cpu.all = all; + _process_cpu.list = list_new; + _process_cpu.ms = Date.now() - _process_cpu.ms; + _process_cpu.result = result; + if (callback) { callback(result) } + resolve(result); + }) + } else { if (callback) { callback(result) } resolve(result); - }) - } else { - if (callback) { callback(result) } - resolve(result); + } } - } - }); + }); + } + if (_windows) { + exec("wmic process get /value", function (error, stdout) { + if (!error) { + let psections = stdout.split(/\n\s*\n/); + let procs = []; + let procStats = []; + let list_new = {}; + let allcpuu = 0; + let allcpus = 0; + for (let i = 0; i < psections.length; i++) { + if (psections[i].trim() !== "") { + let lines = psections[i].trim().split('\r\n'); + let pid = parseInt(util.getValue(lines, 'ProcessId', '=', true), 10); + let statusValue = util.getValue(lines, 'ExecutionState', '=') + let name = util.getValue(lines, 'Caption', '=', true); + let commandLine = util.getValue(lines, 'CommandLine', '=', true); + let utime = parseInt(util.getValue(lines, 'UserModeTime', '=', true), 10); + let stime = parseInt(util.getValue(lines, 'KernelModeTime', '=', true), 10); + let mem = parseInt(util.getValue(lines, 'WorkingSetSize', '=', true), 10); + allcpuu = allcpuu + utime; + allcpus = allcpus + stime; + result.all++; + if (!statusValue) { result.unknown++} + if (statusValue === '3') { result.running++} + if (statusValue === '4' || statusValue === '5') { result.blocked++} + + procStats.push({ + pid: pid, + utime: utime, + stime: stime, + pcpu: 0, + pcpuu: 0, + pcpus: 0, + }); + procs.push({ + pid: pid, + name: name, + pcpu: 0, + pcpuu: 0, + pcpus: 0, + pmem: mem / os.totalmem() * 100, + priority: parseInt(util.getValue(lines, 'Priority', '=', true), 10), + mem_vsz: parseInt(util.getValue(lines, 'PageFileUsage', '=', true), 10), + mem_rss: Math.floor(parseInt(util.getValue(lines, 'WorkingSetSize', '=', true), 10) / 1024), + nice: 0, + started: parseTimeWin(util.getValue(lines, 'CreationDate', '=', true)), + state: (!statusValue ? _winStatusValues[0] : _winStatusValues[statusValue]), + tty: '', + user: '', + command: commandLine || name + }); + } + } + result.sleeping = result.all - result.running - result.blocked - result.unknown; + result.list = procs; + for (let i = 0; i < procStats.length; i++) { + let resultProcess = calcProcPidStat(procStats[i], allcpuu + allcpus); + + // store pcpu in outer array + let listPos = result.list.map(function (e) { return e.pid; }).indexOf(resultProcess.pid); + if (listPos >= 0) { + result.list[listPos].pcpu = resultProcess.pcpuu + resultProcess.pcpus; + result.list[listPos].pcpuu = resultProcess.pcpuu; + result.list[listPos].pcpus = resultProcess.pcpus; + } + + // save new values + list_new[resultProcess.pid] = { + pcpuu: resultProcess.pcpuu, + pcpus: resultProcess.pcpus, + utime: resultProcess.utime, + stime: resultProcess.stime + } + } + // store old values + _process_cpu.all = allcpuu + allcpus; + _process_cpu.list = list_new; + _process_cpu.ms = Date.now() - _process_cpu.ms; + _process_cpu.result = result; + } + if (callback) { + callback(result) + } + resolve(result); + }) + } } else { if (callback) { callback(_process_cpu.result) } resolve(_process_cpu.result); diff --git a/lib/util.js b/lib/util.js index c069922..fa8f450 100644 --- a/lib/util.js +++ b/lib/util.js @@ -57,7 +57,30 @@ function cores() { return _cores; } +function getValue(lines, property, separator, trimmed) { + separator = separator || ':'; + property = property.toLowerCase(); + trimmed = trimmed || false; + for (let i = 0; i < lines.length; i++) { + let line = lines[i].toLowerCase(); + if (trimmed) { + line = line.trim(); + } + if (line.toLowerCase().startsWith(property)) { + const parts = lines[i].split(separator); + if (parts.length >= 2) { + parts.shift(); + return parts.join(':').trim(); + } else { + return '' + } + } + } + return ''; +} + exports.isFunction = isFunction; exports.unique = unique; exports.sortByKey= sortByKey; exports.cores = cores; +exports.getValue = getValue;