From 9b644bbe2a5f301279d2dab94ace35e569df0c66 Mon Sep 17 00:00:00 2001 From: Sebastian Hildebrandt Date: Fri, 15 Sep 2017 15:04:20 +0200 Subject: [PATCH] extended windows support services(), optimized diskLayout() (OSX), bugfixes --- CHANGELOG.md | 1 + README.md | 7 +-- lib/filesystem.js | 41 +++++++++++++++- lib/processes.js | 116 ++++++++++++++++++++++++++++++++-------------- 4 files changed, 125 insertions(+), 40 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 20c8118..957d342 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -98,6 +98,7 @@ Other changes | Version | Date | Comment | | -------------- | -------------- | -------- | +| 3.29.0 | 2017-09-15 | extended windows support `services()`, optimized `diskLayout()` (OSX), bugfixes | | 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 | diff --git a/README.md b/README.md index 0bb1238..bcd0bef 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,7 @@ async function cpu() { ## News and Changes ### Latest Activity +- Version 3.29.0: extended windows support `services()` - 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 @@ -357,9 +358,9 @@ I also created a nice little command line tool called [mmon][mmon-github-url] ( | | pid | X | X | | PID | | | cpu | X | X | | process % CPU | | | mem | X | X | | process % MEM | -| si.services('mysql, apache2', cb) | [{...}] | X | X | | pass comma separated string of services | -| | [0].name | X | X | | name of service | -| | [0].running | X | X | | true / false | +| si.services('mysql, apache2', cb) | [{...}] | X | X | X | pass comma separated string of services | +| | [0].name | X | X | X | name of service | +| | [0].running | X | X | X | true / false | | | [0].pcpu | X | X | | process % CPU | | | [0].pmem | X | X | | process % MEM | diff --git a/lib/filesystem.js b/lib/filesystem.js index 0f5b04e..7b950ac 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -612,11 +612,14 @@ function diskLayout(callback) { } if (_darwin) { - exec("system_profiler SPSerialATADataType", function (error, stdout) { + exec("system_profiler SPSerialATADataType SPNVMeDataType", function (error, stdout) { if (!error) { - let devices = stdout.toString().split(' Physical Interconnect: SATA'); + let parts = stdout.toString().split('NVMExpress:'); + + let devices = parts[0].split(' Physical Interconnect: '); devices.shift(); devices.forEach(function (device) { + device = 'InterfaceType: ' + device; let lines = device.split('\n'); const mediumType = util.getValue(lines, 'Medium Type', ':', true).trim(); const sizeStr = util.getValue(lines, 'capacity', ':', true).trim(); @@ -645,6 +648,40 @@ function diskLayout(callback) { } } }); + if (parts.length > 1) { + let devices = parts[1].split('\n\n Capacity:'); + devices.shift(); + devices.forEach(function (device) { + device = '!Capacity: ' + device; + let lines = device.split('\n'); + const linkWidth = util.getValue(lines, 'link width', ':', true).trim(); + const sizeStr = util.getValue(lines, '!capacity', ':', true).trim(); + if (sizeStr) { + let size = parseInt(sizeStr.match(/\(([^)]+)\)/)[1].replace(/\./g, "")); + if (!size) { + size = parseInt(sizeStr); + } + if (size) { + result.push({ + type: 'NVMe', + name: util.getValue(lines, 'Model', ':', true).trim(), + vendor: '', + size: size, + bytesPerSector: -1, + totalCylinders: -1, + totalHeads: -1, + totalSectors: -1, + totalTracks: -1, + tracksPerCylinder: -1, + sectorsPerTrack: -1, + firmwareRevision: util.getValue(lines, 'Revision', ':', true).trim(), + serialNum: util.getValue(lines, 'Serial Number', ':', true).trim(), + interfaceType: ('PCIe ' + linkWidth).trim(), + }) + } + } + }); + } } if (callback) { callback(result) diff --git a/lib/processes.js b/lib/processes.js index 40f54e7..b24b04d 100644 --- a/lib/processes.js +++ b/lib/processes.js @@ -70,35 +70,84 @@ function services(srv, callback) { return new Promise((resolve, reject) => { process.nextTick(() => { - if (_windows) { - let error = new Error(NOT_SUPPORTED); - if (callback) { callback(NOT_SUPPORTED) } - reject(error); - } - - srv = srv.trim().replace(/,+/g, " ").replace(/ +/g, " ").replace(/ +/g, "|"); + srv = srv.trim().toLowerCase().replace(/,+/g, " ").replace(/ +/g, " ").replace(/ +/g, "|"); let srvs = srv.split('|'); - let comm = (_darwin) ? "ps -caxm -o pcpu,pmem,comm" : "ps axo pcpu,pmem,comm"; let data = []; - if (srv !== '' && srvs.length > 0) { - exec(comm + " | grep -v grep | egrep '" + srv + "'", function (error, stdout) { - if (!error) { - let lines = stdout.toString().replace(/ +/g, " ").replace(/,+/g, ".").split('\n'); - srvs.forEach(function (srv) { - let ps = lines.filter(function (e) { - return e.indexOf(srv) !== -1 + let dataSrv = []; + + if (_linux || _darwin) { + let comm = (_darwin) ? "ps -caxm -o pcpu,pmem,comm" : "ps axo pcpu,pmem,comm"; + if (srv !== '' && srvs.length > 0) { + exec(comm + " | grep -v grep | egrep '" + srv + "'", function (error, stdout) { + if (!error) { + let lines = stdout.toString().replace(/ +/g, " ").replace(/,+/g, ".").split('\n'); + srvs.forEach(function (srv) { + let ps = lines.filter(function (e) { + return e.indexOf(srv) !== -1 + }); + data.push({ + 'name': srv, + 'running': ps.length > 0, + 'pcpu': parseFloat((ps.reduce(function (pv, cv) { + return pv + parseFloat(cv.trim().split(' ')[0]); + }, 0)).toFixed(2)), + 'pmem': parseFloat((ps.reduce(function (pv, cv) { + return pv + parseFloat(cv.trim().split(' ')[1]); + }, 0)).toFixed(2)) + }) }); + if (callback) { callback(data) } + resolve(data); + } else { + srvs.forEach(function (srv) { + data.push({ + 'name': srv, + 'running': false, + 'pcpu': 0, + 'pmem': 0 + }) + }); + if (callback) { callback(data) } + resolve(data); + } + }); + } else { + if (callback) { callback(data) } + resolve(data); + } + } + if (_windows) { + exec("wmic service get /value", {maxBuffer: 1024 * 1000}, function (error, stdout) { + if (!error) { + let serviceSections = stdout.split(/\n\s*\n/); + for (let i = 0; i < serviceSections.length; i++) { + if (serviceSections[i].trim() !== "") { + let lines = serviceSections[i].trim().split('\r\n'); + let srv = util.getValue(lines, 'Name', '=', true).toLowerCase(); + let started = util.getValue(lines, 'Started', '=', true); + if (srvs.indexOf(srv) >= 0) { + data.push({ + 'name': srv, + 'running': (started === 'TRUE'), + 'pcpu': 0, + 'pmem': 0 + }) + dataSrv.push(srv); + } + } + } + let srvsMissing = srvs.filter(function (e) { + return dataSrv.indexOf(e) === -1 + }); + srvsMissing.forEach(function (srv) { data.push({ 'name': srv, - 'running': ps.length > 0, - 'pcpu': parseFloat((ps.reduce(function (pv, cv) { - return pv + parseFloat(cv.trim().split(' ')[0]); - }, 0)).toFixed(2)), - 'pmem': parseFloat((ps.reduce(function (pv, cv) { - return pv + parseFloat(cv.trim().split(' ')[1]); - }, 0)).toFixed(2)) + 'running': false, + 'pcpu': 0, + 'pmem': 0 }) }); + if (callback) { callback(data) } resolve(data); } else { @@ -113,10 +162,7 @@ function services(srv, callback) { if (callback) { callback(data) } resolve(data); } - }); - } else { - if (callback) { callback(data) } - resolve(data); + }) } }); }); @@ -178,15 +224,15 @@ function processes(callback) { function getName(command) { command = command || ''; - let result = command.split(' '); + let result = command.split(' ')[0]; if (result.substr(-1) === ':') { result = result.substr(0, result.length - 1); } if (result.substr(0,1) !== '[') { - let parts = part.split('/'); - result = parts[parts.length]; + let parts = result.split('/'); + result = parts[parts.length - 1]; } - return result + return result; } function parseLine(line) { @@ -438,17 +484,17 @@ function processes(callback) { }); } if (_windows) { - exec("wmic process get /value", function (error, stdout) { + exec("wmic process get /value", {maxBuffer: 1024 * 1000}, function (error, stdout) { if (!error) { - let psections = stdout.split(/\n\s*\n/); + let processSections = 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'); + for (let i = 0; i < processSections.length; i++) { + if (processSections[i].trim() !== "") { + let lines = processSections[i].trim().split('\r\n'); let pid = parseInt(util.getValue(lines, 'ProcessId', '=', true), 10); let statusValue = util.getValue(lines, 'ExecutionState', '=') let name = util.getValue(lines, 'Caption', '=', true);