From 3e1669e3fb0d3752606643181557c3c8d79c1ab5 Mon Sep 17 00:00:00 2001 From: Sebastian Hildebrandt Date: Tue, 15 Nov 2016 08:47:18 +0100 Subject: [PATCH] blockDevices for OSX and extended blockDevices --- CHANGELOG.md | 7 ++-- README.md | 21 ++++++---- lib/filesystem.js | 104 ++++++++++++++++++++++++++++++++++++++++------ lib/index.js | 1 + 4 files changed, 109 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d27b320..3498bf6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# Changelog +# Changelog ### Major (breaking) Changes - Version 3 @@ -6,10 +6,10 @@ - **Promises**. As you can see above, you can now also use it in a promise oriented way. But callbacks are still supported. - `cpuCurrentspeed`: now returns an object with current minimal, maximal and average CPU frequencies of all cores. - `mem`: now supports also newer versions of `free` (Version 3.3.10 and above); extended information `avaliable` (potentially available memory) -- `fsStats`: added information sum bytes read + write (tx) and sum transfer rate/sec (tx_sec) +- `fsStats`: added information sum bytes read + write (tx) and sum transfer rate/sec (tx_sec) - `networkInterfaces`: now providing one more detail: internal - true if this is an internal interface like "lo" - `networkConnections`: instead of only counting sockets, you now get an array of objects with connection details for each socket (protocol, local and peer address, state) -- `users`: now provides an array of objects with users online including detailed session information (login date/time, ip address, terminal, command) +- `users`: now provides an array of objects with users online including detailed session information (login date/time, ip address, terminal, command) - `inetLatency`: now you can provide a host against which you want to test latency (default is 8.8.8.8) - `getDynamicData`: changed order of parameters (callback - if provided - is now the last one): `getDynamicData(srv, network, callback)` - `getAllData`: changed order of parameters (callback - if provided - is now the last one): `getAllData(srv, network, callback)` @@ -89,6 +89,7 @@ Other changes | Version | Date | Comment | | -------------- | -------------- | -------- | +| 3.11.0 | 2016-11-15 | blockDevices for OSX and extended blockDevices | | 3.10.2 | 2016-11-14 | bug fix fsSize on OSX | | 3.10.1 | 2016-11-14 | optimization fsStats, disksIO, networkStats | | 3.10.0 | 2016-11-12 | added blockDevices, fixed fsSize, added file system type | diff --git a/README.md b/README.md index ba2742a..d275064 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Simple system and OS information library for [node.js][nodejs-url] ## Quick Start -Collection of 25+ functions to retrieve detailed hardware, system and OS information (linux and OSX only) +Collection of 30+ functions to retrieve detailed hardware, system and OS information (linux and OSX only) ### Installation @@ -42,16 +42,17 @@ si.cpu() ### Latest Activity +- Version 3.11.0: blockDevices now also for OSX and also extended (+ label, model, serial, protocol). - Version 3.10.0: added blockDevices (list of disks, partitions, raids and roms). - Version 3.9.0: extended networkInterfaces (added MAC address). - Version 3.8.0: added dockerContainerProcesses (array of processes inside a docker container). - Version 3.7.0: extended docker stats. -- Version 3.6.0: added versions (kernel, ssl, node, npm, pm2, ...). -- Version 3.5.0: added graphics info (controller and display). -- Version 3.4.0: rewritten currentLoad and CPU load for processes (linux). This is now much more accurate. -- Version 3.3.0: added process list. Get full process list including details like cpu and mem usage, status, command, ... -- Version 3.2.0: added battery support. If a battery is installed, you get information about status and current capacity level -- Version 3.1.0: added [Docker][docker-url] support. Now you can scan your docker containers and get their stats +- Version 3.6.0: added versions (kernel, ssl, node, npm, pm2, ...). +- Version 3.5.0: added graphics info (controller and display). +- Version 3.4.0: rewritten currentLoad and CPU load for processes (linux). This is now much more accurate. +- Version 3.3.0: added process list. Get full process list including details like cpu and mem usage, status, command, ... +- Version 3.2.0: added battery support. If a battery is installed, you get information about status and current capacity level +- Version 3.1.0: added [Docker][docker-url] support. Now you can scan your docker containers and get their stats - Version 3.0.0: added DisksIO - overall diskIO and IOPS values for all mounted volumes ### Changelog @@ -174,6 +175,10 @@ This library is splitted in several sections: | - [0].size | X | X | size in bytes | | - [0].physical | X | X | physical type (HDD, SSD, CD/DVD) | | - [0].uuid | X | X | UUID | +| - [0].label | X | X | label | +| - [0].model | X | X | model | +| - [0].serial | X | | serial | +| - [0].protocol | X | X | protocol (SATA, PCI-Express, ...) | | si.fsStats(cb) | X | X | current transfer stats | | - rx | X | X | bytes read since startup | | - wx | X | X | bytes written since startup | @@ -314,7 +319,7 @@ si.networkStats('eth1', function(data) { ### Promises -**Promises Style** is new in version 3.0. +**Promises Style** is new in version 3.0. When omitting callback parameter (cb), then you can use all function in a promise oriented way. All functions (exept of `version` and `time`) are returning a promis, that you can consume: diff --git a/lib/filesystem.js b/lib/filesystem.js index 789539f..b764e9e 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -72,6 +72,68 @@ exports.fsSize = fsSize; // -------------------------- // disks +function parseBytes(s) { + return parseInt(s.substr(s.indexOf(' (')+2, s.indexOf(' Bytes)')-10)) +} + +function parseDevices (lines) { + let devices = []; + let i = 0; + lines.forEach(line => { + if (line.length > 0) { + if (line[0] == '*') { + i++; + } else { + let parts = line.split(':'); + if (parts.length > 1) { + if (!devices[i]) devices[i] = { + name: '', + identifier: '', + type: 'disk', + fstype: '', + mount: '', + size: 0, + physical: 'HDD', + uuid: '', + label: '', + model: '', + serial: '', + protocol: '' + }; + parts[0] = parts[0].trim().toUpperCase().replace(/ +/g, ''); + parts[1] = parts[1].trim(); + if ('DEVICEIDENTIFIER' == parts[0]) devices[i].identifier = parts[1]; + if ('DEVICENODE' == parts[0]) devices[i].name = parts[1]; + if ('VOLUMENAME' == parts[0]) { if (parts[1].indexOf('Not applicable') == -1) devices[i].label = parts[1]; } + if ('PROTOCOL' == parts[0]) devices[i].protocol = parts[1]; + if ('DISKSIZE' == parts[0]) devices[i].size = parseBytes(parts[1]); + if ('FILESYSTEMPERSONALITY' == parts[0]) devices[i].fstype = parts[1]; + if ('MOUNTPOINT' == parts[0]) devices[i].mount = parts[1]; + if ('VOLUMEUUID' == parts[0]) devices[i].uuid = parts[1]; + if ('READ-ONLYMEDIA' == parts[0] && parts[1] == 'Yes') devices[i].physical = 'CD/DVD'; + if ('SOLIDSTATE' == parts[0] && parts[1] == 'Yes') devices[i].physical = 'SSD'; + if ('VIRTUAL' == parts[0]) devices[i].type = 'virtual'; + if ('PARTITIONTYPE' == parts[0]) devices[i].type = 'part'; + if ('DEVICE/MEDIANAME' == parts[0]) devices[i].model = parts[1]; + } + } + } + }); + return devices; +} + +function fromTo(header, label) { + let from = header.indexOf(label); + let to = from + label.length; + for (let i = to; i < header.length && header[i] == ' '; i++) { + to = i + } + console.log(label + ' - ' + from + ' ' + to); + return { + from: from, + to: to + } +} function blockDevices(callback) { return new Promise((resolve, reject) => { @@ -83,18 +145,23 @@ function blockDevices(callback) { } if (_linux) { - exec("lsblk -bo NAME,TYPE,SIZE,FSTYPE,MOUNTPOINT,UUID,ROTA,OWNER,GROUP,MODE,LABEL,ALIGNMENT,MIN-IO,OPT-IO,PHY-SEC,LOG-SEC,SCHED,RQ-SIZE,RA,WSAME", function (error, stdout) { + // see https://wiki.ubuntuusers.de/lsblk/ + exec("lsblk -bo NAME,TYPE,SIZE,FSTYPE,MOUNTPOINT,UUID,ROTA,RO,TRAN,SERIAL,LABEL,MODEL,OWNER,GROUP,MODE,ALIGNMENT,MIN-IO,OPT-IO,PHY-SEC,LOG-SEC,SCHED,RQ-SIZE,RA,WSAME", function (error, stdout) { let data = []; if (!error) { let lines = stdout.toString().split('\n'); let header = lines[0]; + let ft_label = fromTo(header, 'LABEL'); + let ft_model = fromTo(header, 'MODEL'); + let ft_serial = fromTo(header, 'SERIAL'); lines.splice(0, 1); - lines.forEach(function (line) { - if (line != '') { - if (line.substr(header.indexOf('FSTYPE'), 1) == ' ') { line = line.substr(0, header.indexOf('FSTYPE')) + '-' + line.substr(header.indexOf('FSTYPE') + 1, 1000)} - if (line.substr(header.indexOf('MOUNTPOINT'), 1) == ' ') { line = line.substr(0, header.indexOf('MOUNTPOINT')) + '-' + line.substr(header.indexOf('MOUNTPOINT') + 1, 1000)} - if (line.substr(header.indexOf('UUID'), 1) == ' ') { line = line.substr(0, header.indexOf('UUID')) + '-' + line.substr(header.indexOf('UUID') + 1, 1000)} - line = line.replace(/[├─│└]+/g, ""); + lines.forEach(orgline => { + if (orgline != '') { + if (orgline.substr(header.indexOf('FSTYPE'), 1) == ' ') { orgline = orgline.substr(0, header.indexOf('FSTYPE')) + '-' + orgline.substr(header.indexOf('FSTYPE') + 1, 1000)} + if (orgline.substr(header.indexOf('MOUNTPOINT'), 1) == ' ') { orgline = orgline.substr(0, header.indexOf('MOUNTPOINT')) + '-' + orgline.substr(header.indexOf('MOUNTPOINT') + 1, 1000)} + if (orgline.substr(header.indexOf('UUID'), 1) == ' ') { orgline = orgline.substr(0, header.indexOf('UUID')) + '-' + orgline.substr(header.indexOf('UUID') + 1, 1000)} + if (orgline.substr(header.indexOf('TRAN'), 1) == ' ') { orgline = orgline.substr(0, header.indexOf('TRAN')) + '-' + orgline.substr(header.indexOf('TRAN') + 1, 1000)} + let line = orgline.replace(/[├─│└]+/g, ""); line = line.replace(/ +/g, " ").trim().split(' '); data.push({ 'name': line[0], @@ -103,7 +170,11 @@ function blockDevices(callback) { 'mount': (line[4] == '-' ? '' : line[4]), 'size': parseInt(line[2]), 'physical': (line[1] == 'disk' ? (line[6] == '0' ? 'SSD' : 'HDD') : (line[1] == 'rom' ? 'CD/DVD' : '')), - 'uuid': (line[5] == '-' ? '' : line[5]) + 'uuid': (line[5] == '-' ? '' : line[5]), + 'label': orgline.substring(ft_label.from, ft_label.to).trim(), + 'model': orgline.substring(ft_model.from, ft_model.to).trim(), + 'serial': orgline.substring(ft_serial.from, ft_serial.to).trim(), + 'protocol': (line[8] == '-' ? '' : line[8]) }) } }); @@ -118,11 +189,18 @@ function blockDevices(callback) { } if (_darwin) { // last minute decision to remove code ... not stable - let data = []; - if (callback) { - callback(data) - } - resolve(data); + exec("diskutil info -all", function (error, stdout) { + let data = []; + if (!error) { + let lines = stdout.toString().split('\n'); + // parse lines into temp array of devices + data = parseDevices(lines); + } + if (callback) { + callback(data) + } + resolve(data); + }); } }); }); diff --git a/lib/index.js b/lib/index.js index 8faa714..22a33fb 100644 --- a/lib/index.js +++ b/lib/index.js @@ -81,6 +81,7 @@ // -------------------------------- // // version date comment +// 3.11.0 2016-11-15 blockDevices for OSX and extended blockDevices // 3.10.2 2016-11-14 bug fix fsSize on OSX // 3.10.1 2016-11-14 optimization fsStats, disksIO, networkStats // 3.10.0 2016-11-12 added blockDevices, fixed fsSize, added file system type