diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..3087260
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,23 @@
+# For more information about the properties used in
+# this file, please see the EditorConfig documentation:
+# http://editorconfig.org/
+
+# top-most EditorConfig file
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+indent_style = space
+indent_size = 2
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.md]
+trim_trailing_whitespace = true
+
+[{.travis.yml,package.json}]
+# The indent size used in the `package.json` file cannot be changed
+# https://github.com/npm/npm/pull/3180#issuecomment-16336516
+indent_style = space
+indent_size = 2
diff --git a/README.md b/README.md
index 79f780b..db759a4 100644
--- a/README.md
+++ b/README.md
@@ -4,6 +4,8 @@ Simple system and OS information library for [node.js][nodejs-url]
[![NPM Version][npm-image]][npm-url]
[![NPM Downloads][downloads-image]][downloads-url]
+ [![Git Issues][issues-img]][issues-url]
+ [![deps status][daviddm-img]][daviddm-url]
[![MIT license][license-img]][license-url]
## Quick Start
@@ -21,19 +23,52 @@ All functions (except `version` and `time`) are implemented as asynchronous func
```
var si = require('systeminformation');
+// callback style
si.cpu(function(data) {
console.log('CPU-Information:');
console.log(data);
})
+
+// promises style
+si.cpu()
+ .then(data => console.log(data))
+ .catch(error => console.error(error));
+
```
-### Major Changes - Version 2
+### Major (breaking) Changes - Version 3
-There are a lot of changes in version 2 of systeminformation! Here is a quick overview:
+- works only with [node.js][nodejs-url] **v4.0.0** and above (using now internal ES6 promise function, arrow functions, ...)
+- **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.
+- `networkInterfaces`: now providing one more detail: internal - true if this is an internal interface like "lo"
+- `mem`: now supports also `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)
+- `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)
+- `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)`
-New Functions
+New Functions
-- `version`: returns systeminformation version (semver)
+- `disksIO`: returns overall diskIO and IOPS values for all mounted volumes
+
+Bug Fixes
+
+- several bug fixes (like assess errors)
+- testet on even more platforms and linux distributions
+
+**Be aware**, that the new version 3.x is **NOT fully backward compatible** to version 2.x ...
+
+
+### Major (breaking) Changes - Version 2
+
+There had been a lot of changes in version 2 of systeminformation! Here is a quick overview (for those who come from version 1):
+
+New Functions
+
+- `version`: returns systeminformation version (semver) of this library
- `system`: hardware info (manufacturer, product/model name, version, serial, uuid)
- `networkConnections`: number of active connections
- `inetLatency`: latency in ms to external resource (internet)
@@ -61,12 +96,12 @@ Function Changes
- `cpu_temperature`/`cpuTemperature`: -1 is new default (and indicates that non sensors are installed)
- `cpu_temperature`/`cpuTemperature`: new result `max` which returns max temperature of all cores
- `cpu_currentspeed`/`cpuCurrentspeed`: now in GHz
-- `cpu`: splitted `manufacturer` (e.g. Intel) and `brand` (e.g. Core 2 Duo)
+- `cpu`: splitted `manufacturer` (e.g. Intel) and `brand` (e.g. Core 2 Duo)
- `network_speed`/`networkStats`: now better support for OS X (also support for `operstate`)
-- `network_speed`/`networkStats`: overall received and transferred bytes (rx, tx)
+- `network_speed`/`networkStats`: overall received and transferred bytes (rx, tx)
- `mem`: now better support for OS X (also support for `swaptotal`, `swapused`, `swapfree`)
-- `fs_size`/`fsSize`: use-values now in % (0 - 100% instead of 0 - 1)
-- `fs_speed`/`fsStats`: now also full support for OS X
+- `fs_size`/`fsSize`: use-values now in % (0 - 100% instead of 0 - 1)
+- `fs_speed`/`fsStats`: now also full support for OS X
- `checksite`/`inetChecksite`: new result structure - see command reference
- `checksite`/`inetChecksite`: ms (former `response_ms`): -1 if not ok
@@ -75,15 +110,14 @@ Other changes
- no more external dependencies: `request` is not longer needed
- where possible results are now integer or float values (instead of strings) because it is easier to calculate with numbers ;-)
-**Be aware**, that the new version 2.x is **NOT backward compatible** to version 1.x ....
-
## Core concept
-[Node.js][nodejs-url] comes with some basic OS information, but I always wanted a little more. So I came up to write this
-little library. This library is still work in progress. In version 2 I cleaned up a lot of inconsistencies and bugs, but
-there is for sure room for improvement. I was only able to test it on several Debian, Raspbian, Ubuntu distributions as well
-as OS X (Mavericks, Yosemite, El Captain). Version 2 now also supports nearly all functionality on OS X/Darwin platforms.
-But be careful, this library will definitely NOT work on Windows platforms!
+[Node.js][nodejs-url] comes with some basic OS information, but I always wanted a little more. So I came up to write this
+little library. This library is still work in progress. Version 3 comes with further improvements. First it
+requires now node.js version 4.0 and above. Another big change is, that all functions now return promises. You can use them
+like before with callbacks OR with promises (see example in this documentation). I am sure, there is for sure room for improvement.
+I was only able to test it on several Debian, Raspbian, Ubuntu distributions as well as OS X (Mavericks, Yosemite, El Captain).
+Since version 2 nearly all functionality is available on OS X/Darwin platforms. But be careful, this library will definitely NOT work on Windows platforms!
If you have comments, suggestions & reports, please feel free to contact me!
@@ -133,17 +167,21 @@ This library is splitted in several sections:
| - brand | X | X | e.g. 'Core(TM)2 Duo' |
| - speed | X | X | in GHz e.g. '3.40' |
| - cores | X | X | # cores |
-| si.cpuCurrentspeed(cb) | X | X | current speed (in GHz)|
+| si.cpuCurrentspeed(cb) | X | X | current CPU speed (in GHz)|
+| - avg | X | | avg CPU speed (all cores) |
+| - min | X | | min CPU speed (all cores) |
+| - max | X | | max CPU speed (all cores) |
| si.cpuTemperature(cb) | X | | CPU temperature (if sensors is installed) |
| - main | X | | main temperature |
| - cores | X | | array of temperatures |
| - max | X | | max temperature |
| si.mem(cb) | X | X | Memory information|
-| - total | X | X | |
-| - free | X | X | |
-| - used | X | X | |
-| - active | X | X | |
-| - buffcache | X | X | |
+| - total | X | X | total memory |
+| - free | X | X | not used |
+| - used | X | X | used (incl. buffers/cache) |
+| - active | X | X | used actively (excl. buffers/cache) |
+| - buffcache | X | X | used by buffers+cache |
+| - available | X | X | potentially available (total - active) |
| - swaptotal | X | X | |
| - swapused | X | X | |
| - swapfree | X | X | |
@@ -156,19 +194,39 @@ This library is splitted in several sections:
| si.fsStats(cb) | X | X | current transfer stats |
| - rx | X | X | bytes read since startup |
| - wx | X | X | bytes written since startup |
+| - tx | X | X | total bytes read + written since startup |
| - rx_sec | X | X | bytes read / second (* see notes) |
| - wx_sec | X | X | bytes written / second (* see notes) |
+| - tx_sec | X | X | total bytes reads + written / second |
+| - ms | X | X | interval length (for per second values) |
+| si.disksIO(cb) | X | X | current transfer stats |
+| - rIO | X | X | read IOs on all mounted drives |
+| - wIO | X | X | write IOs on all mounted drives |
+| - tIO | X | X | write IOs on all mounted drives |
+| - rIO_sec | X | X | read IO per sec (* see notes) |
+| - wIO_sec | X | X | write IO per sec (* see notes) |
+| - tIO_sec | X | X | total IO per sec (* see notes) |
+| - ms | X | | interval length (for per second values) |
| si.networkInterfaces(cb) | X | X | array of network interfaces |
| - [0].iface | X | X | interface name |
| - [0].ip4 | X | X | ip4 address |
| - [0].ip6 | X | X | ip6 address |
-| si.networkStats('eth1',cb) | X | X | current network stats of given interface |
+| - [0].internal | X | X | true if internal interface |
+| si.networkStats(iface,cb) | X | X | current network stats of given interface
iface parameter is optional
defaults to first external network interface|
| - iface | X | X | interface |
| - operstate | X | X | up / down |
| - rx | X | X | received bytes overall |
| - tx | X | X | transferred bytes overall|
| - rx_sec | X | X | received bytes / second (* see notes) |
| - tx_sec | X | X | transferred bytes per second (* see notes) |
+| - ms | X | X | interval length (for per second values) |
+| si.networkConnections(cb) | X | X | current network network connections
returns an array of all connections|
+| - [0].protocol | X | X | tcp or udp |
+| - [0].localaddress | X | X | local address |
+| - [0].localport | X | X | local port |
+| - [0].peeraddress | X | X | peer address |
+| - [0].peerport | X | X | peer port |
+| - [0].state | X | X | like ESTABLISHED, TIME_WAIT, ... |
| si.currentLoad(cb) | X | X | CPU-Load in % |
| si.fullLoad(cb) | X | X | CPU-full load since bootup in % |
| si.services('mysql, apache2', cb) | X | X | pass comma separated string of services |
@@ -183,20 +241,27 @@ This library is splitted in several sections:
| - cpu | X | X | process % CPU |
| - mem | X | X | process % MEM |
| si.users(cb) | X | X | array of users online |
+| - [0].user | X | X | user name |
+| - [0].tty | X | X | terminal |
+| - [0].date | X | X | login date |
+| - [0].time | X | X | login time |
+| - [0].ip | X | X | ip address (remote login) |
+| - [0].command | X | X | last command or shell |
| si.inetChecksite(url, cb) | X | X | response-time (ms) to fetch given URL |
| - url | X | X | given url |
| - ok | X | X | status code OK (2xx, 3xx) |
| - status | X | X | status code |
| - ms | X | X | response time in ms |
-| si.inetLatency(cb) | X | X | response-time (ms) to external ressource |
+| si.inetLatency(host, cb) | X | X | response-time (ms) to external resource
host parameter is optional (default 8.8.8.8)|
| si.getStaticData(cb) | X | X | all static data at once |
-| si.getDynamicData(cb,srv,iface) | X | X | all dynamic data at once |
-| si.getAllData(cb,srv,iface) | X | X | all data at once |
+| si.getDynamicData(srv,iface,cb) | X | X | all dynamic data at once |
+| si.getAllData(srv,iface,cb) | X | X | all data at once |
### cb: Asynchronous Function Calls (callback)
-Remember: all functions (except `version` and `time`) are implemented as asynchronous (callback) functions!
-So another example, how to use a specific function might be:
+Remember: all functions (except `version` and `time`) are implemented as asynchronous functions! There are now two ways to consume them:
+
+**Callback Style**
```
var si = require('systeminformation');
@@ -211,17 +276,35 @@ si.networkStats('eth1', function(data) {
})
```
+**Promises Style** (new in version 3.0)
+
+When omitting callback parameter (cb), then you can use all function in a promise oriented way:
+
+```
+si.networkStats('eth1')
+ .then(data => {
+ console.log('Network Interface Stats (eth1):');
+ console.log('- is up: ' + data.operstate);
+ console.log('- RX bytes overall: ' + data.rx);
+ console.log('- TX bytes overall: ' + data.tx);
+ console.log('- RX bytes/sec: ' + data.rx_sec);
+ console.log('- TX bytes/sec: ' + data.tx_sec);
+ })
+ .catch(error => console.error(error));
+
+```
+
### *: Additional Notes
-In `fsStats` and `networkStats` the results per second values (rx_sec, ...) are calculated beginning
-with the second call of the function. It is determined by calculating the difference of transferred bytes
+In `fsStats`, `disksIO` and `networkStats` the results per second values (rx_sec, IOPS, ...) are calculated beginning
+with the second call of the function. It is determined by calculating the difference of transferred bytes / IOs
divided by the time between two calls of the function.
## Known Issues
There is one major things, that I was still not able to solve:
-For OS X, I did not find a reliable way to get the CPU temperature. All suggestions I found did not work on current version of OS X on different machines (intel platform). So if anyone has an idea, this would be helpful.
+For OS X, I did not find a reliable way to get the CPU temperature. All suggestions I found did not work on current version of OS X on different machines (intel platform). So if anyone has an idea, this would be helpful.
I am happy to discuss any comments and suggestions. Please feel free to contact me if you see any possibility of improvement!
@@ -229,6 +312,7 @@ I am happy to discuss any comments and suggestions. Please feel free to contact
| Version | Date | Comment |
| -------------- | -------------- | -------- |
+| 3.0.0 | 2016-08-02 | new major version 3.0 |
| 2.0.5 | 2016-03-02 | changed .gitignore |
| 2.0.4 | 2016-02-22 | tiny correction - removed double quotes CPU brand, ... |
| 2.0.3 | 2016-02-22 | optimized cpuCurrentspeed |
@@ -266,13 +350,14 @@ Written by Sebastian Hildebrandt [sebhildebrandt](https://github.com/sebhildebra
- Guillaume Legrain [glegrain](https://github.com/glegrain)
- Riccardo Novaglia [richy24](https://github.com/richy24)
+- Quentin Busuttil [Buzut](https://github.com/Buzut)
## Copyright Information
-Linux is a registered trademark of Linus Torvalds, OS X is a registered trademark of Apple Inc.,
-Windows is a registered trademark of Microsoft Corporation. Node.js is a trademark of Joyent Inc.,
-Intel is a trademark of Intel Corporation, Raspberry Pi is a trademark of the Raspberry Pi Foundation,
-Debian is a trademark of the Debian Project, Ubuntu is a trademark of Canonical Ltd.
+Linux is a registered trademark of Linus Torvalds, OS X is a registered trademark of Apple Inc.,
+Windows is a registered trademark of Microsoft Corporation. Node.js is a trademark of Joyent Inc.,
+Intel is a trademark of Intel Corporation, Raspberry Pi is a trademark of the Raspberry Pi Foundation,
+Debian is a trademark of the Debian Project, Ubuntu is a trademark of Canonical Ltd.
All other trademarks are the property of their respective owners.
## License [![MIT license][license-img]][license-url]
@@ -298,7 +383,7 @@ All other trademarks are the property of their respective owners.
>LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
>OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
>THE SOFTWARE.
->
+>
>Further details see [LICENSE](LICENSE) file.
@@ -312,3 +397,9 @@ All other trademarks are the property of their respective owners.
[npmjs-license]: https://img.shields.io/npm/l/systeminformation.svg?style=flat-square
[nodejs-url]: https://nodejs.org/en/
+
+[daviddm-img]: https://img.shields.io/david/sebhildebrandt/systeminformation.svg?style=flat-square
+[daviddm-url]: https://david-dm.org/sebhildebrandt/systeminformation
+
+[issues-img]: https://img.shields.io/github/issues/sebhildebrandt/systeminformation.svg?style=flat-square
+[issues-url]: https://github.com/sebhildebrandt/systeminformation/issues
diff --git a/lib/index.js b/lib/index.js
index 167f81c..a885f5c 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -1,3 +1,4 @@
+'use strict';
// ==================================================================================
// index.js
// ----------------------------------------------------------------------------------
@@ -8,6 +9,7 @@
// ----------------------------------------------------------------------------------
// Contributors: Guillaume Legrain (https://github.com/glegrain)
// Riccardo Novaglia (https://github.com/richy24)
+// Quentin Busuttil (https://github.com/Buzut)
// ----------------------------------------------------------------------------------
// License: MIT
// ==================================================================================
@@ -33,7 +35,7 @@
//
// # npm install systeminformation --save
//
-// The new version 2.0 has no more dependencies.
+// Since version 2.0 systeminformation has no more dependencies.
//
// ==================================================================================
//
@@ -43,20 +45,28 @@
//
// var si = require('systeminformation');
//
+// // callback style
// si.cpu(function(data) {
// console.log('CPU-Information:');
// console.log(data);
// })
//
+// // promises style
+// si.cpu()
+// .then(data => console.log(data))
+// .catch(error => console.error(error));
+//
// ==================================================================================
//
// Comments
// --------------------------------
//
-// This library is still work in progress. In version 2 I cleaned up a lot of inconsistencies
-// and bugs, but there is for sure room for improvement. I was only able to test it on several
+// This library is still work in progress. Version 3 comes with further improvements. First it
+// requires now node.js version 4.0 and above. Another big change is, that all functions now
+// return promises. You can use them like before with callbacks OR with promises (see documentation
+// below. I am sure, there is for sure room for improvement. I was only able to test it on several
// Debian, Raspbian, Ubuntu distributions as well as OS X (Mavericks, Yosemite, El Captain).
-// Version 2 now also supports nearly all functionality on OS X/Darwin platforms.
+// Since version 2 nearly all functionality is available on OS X/Darwin platforms.
// But be careful, this library will definitely NOT work on Windows platforms!
//
// Comments, suggestions & reports are very welcome!
@@ -67,6 +77,8 @@
// --------------------------------
//
// version date comment
+// 3.0.0 2016-08-01 new major version 3.0
+// 2.0.5 2016-02-22 some more tiny correction ...
// 2.0.4 2016-02-22 tiny correction - removed double quotes CPU brand, ...
// 2.0.3 2016-02-22 optimized cpuCurrentspeed
// 2.0.2 2016-02-22 added CoreOS identification
@@ -90,7 +102,7 @@
// Dependencies
// ----------------------------------------------------------------------------------
-var os = require('os')
+const os = require('os')
, exec = require('child_process').exec
, fs = require('fs')
, lib_version = require('../package.json').version;
@@ -103,6 +115,8 @@ var _windows = (_platform == 'Windows_NT');
var _network = {};
var _cpu_speed = '0.00';
var _fs_speed = {};
+var _disk_io = {};
+var _default_iface;
const NOT_SUPPORTED = 'not supported';
@@ -111,8 +125,8 @@ const NOT_SUPPORTED = 'not supported';
// ----------------------------------------------------------------------------------
function isFunction(functionToCheck) {
- var getType = {};
- return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
+ var getType = {};
+ return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
}
// ----------------------------------------------------------------------------------
@@ -120,105 +134,113 @@ function isFunction(functionToCheck) {
// ----------------------------------------------------------------------------------
function system(callback) {
- if (_windows) {
- callback(NOT_SUPPORTED);
- }
- var result = {
- manufacturer : '-',
- model : '-',
- version : '-',
- serial : '-',
- uuid : '-'
- };
+ return new Promise((resolve, reject) => {
+ process.nextTick(() => {
+ if (_windows) {
+ let error = new Error(NOT_SUPPORTED);
+ if (callback) { callback(NOT_SUPPORTED) }
+ reject(error);
+ }
- if (_linux) {
- exec("dmidecode -t system", function(error, stdout) {
- if (!error) {
- var lines = stdout.toString().split('\n');
- lines.forEach(function(line) {
- if (line.indexOf(':') != -1) {
- if (line.toLowerCase().indexOf('manufacturer') != -1) result.manufacturer = line.split(':')[1].trim();
- if (line.toLowerCase().indexOf('product name') != -1) result.model = line.split(':')[1].trim();
- if (line.toLowerCase().indexOf('version') != -1) result.version = line.split(':')[1].trim();
- if (line.toLowerCase().indexOf('serial number') != -1) result.serial = line.split(':')[1].trim();
- if (line.toLowerCase().indexOf('uuid') != -1) result.uuid = line.split(':')[1].trim();
- }
- });
- if (result.serial.toLowerCase().indexOf('o.e.m.') != -1) result.serial = '-';
+ var result = {
+ manufacturer: '-',
+ model: '-',
+ version: '-',
+ serial: '-',
+ uuid: '-'
+ };
- if (result.manufacturer == '-' && result.model == '-' && result.version == '-') {
- // Check Raspberry Pi
- exec("grep Hardware /proc/cpuinfo; grep Serial /proc/cpuinfo; grep Revision /proc/cpuinfo", function(error, stdout) {
- if (!error) {
- var lines = stdout.toString().split('\n');
- lines.forEach(function(line) {
- if (line.indexOf(':') != -1) {
- if (line.toLowerCase().indexOf('hardware') != -1) result.model = line.split(':')[1].trim();
- if (line.toLowerCase().indexOf('revision') != -1) result.version = line.split(':')[1].trim();
- if (line.toLowerCase().indexOf('serial') != -1) result.serial = line.split(':')[1].trim();
- }
- });
- if (result.model == 'BCM2709') {
- result.manufacturer = 'Raspberry Pi Foundation';
- result.model = result.model + ' - Pi 2 Model B';
- if (['a01041', 'a21041'].indexOf(result.version) >= 0) {
- result.version = result.version + ' - Rev. 1.1'
- }
- }
- if (result.model == 'BCM2708') {
- result.manufacturer = 'Raspberry Pi Foundation';
- if (['0002', '0003'].indexOf(result.version) >= 0) {
- result.model = result.model + ' - Pi Model B';
- result.version = result.version + ' - Rev 1.0';
- }
- if (['0007', '0008', '0009'].indexOf(result.version) >= 0) {
- result.model = result.model + ' - Pi Model A';
- result.version = result.version + ' - Rev 2.0';
- }
- if (['0004', '0005', '0006', '000d', '000e', '000f'].indexOf(result.version) >= 0) {
- result.model = result.model + ' - Pi Model B';
- result.version = result.version + ' - Rev 2.0';
- }
- if (['0012'].indexOf(result.version) >= 0) {
- result.model = result.model + ' - Pi Model A+';
- result.version = result.version + ' - Rev 1.0';
- }
- if (['0010'].indexOf(result.version) >= 0) {
- result.model = result.model + ' - Pi Model B+';
- result.version = result.version + ' - Rev 1.0';
- }
- if (['0013'].indexOf(result.version) >= 0) {
- result.model = result.model + ' - Pi Model B+';
- result.version = result.version + ' - Rev 1.2';
- }
- }
- }
- })
- }
- }
- callback(result);
- })
- }
- if (_darwin) {
- exec("ioreg -c IOPlatformExpertDevice -d 2", function(error, stdout) {
- if (!error) {
- var lines = stdout.toString().split('\n');
- lines.forEach(function(line) {
- line = line.replace(/[<>"]/g, "");
- if (line.indexOf('=') != -1) {
- if (line.toLowerCase().indexOf('manufacturer') != -1) result.manufacturer = line.split('=')[1].trim();
- if (line.toLowerCase().indexOf('model') != -1) result.model = line.split('=')[1].trim();
- if (line.toLowerCase().indexOf('version') != -1) result.version = line.split('=')[1].trim();
- if (line.toLowerCase().indexOf('ioplatformserialnumber') != -1) result.serial = line.split('=')[1].trim();
- if (line.toLowerCase().indexOf('ioplatformuuid') != -1) result.uuid = line.split('=')[1].trim();
- }
- });
- }
- callback(result);
- })
- }
+ if (_linux) {
+ exec("dmidecode -t system", function (error, stdout) {
+ if (!error) {
+ var lines = stdout.toString().split('\n');
+ lines.forEach(function (line) {
+ if (line.indexOf(':') != -1) {
+ if (line.toLowerCase().indexOf('manufacturer') != -1) result.manufacturer = line.split(':')[1].trim();
+ if (line.toLowerCase().indexOf('product name') != -1) result.model = line.split(':')[1].trim();
+ if (line.toLowerCase().indexOf('version') != -1) result.version = line.split(':')[1].trim();
+ if (line.toLowerCase().indexOf('serial number') != -1) result.serial = line.split(':')[1].trim();
+ if (line.toLowerCase().indexOf('uuid') != -1) result.uuid = line.split(':')[1].trim();
+ }
+ });
+ if (result.serial.toLowerCase().indexOf('o.e.m.') != -1) result.serial = '-';
+ if (result.manufacturer == '-' && result.model == '-' && result.version == '-') {
+ // Check Raspberry Pi
+ exec("grep Hardware /proc/cpuinfo; grep Serial /proc/cpuinfo; grep Revision /proc/cpuinfo", function (error, stdout) {
+ if (!error) {
+ var lines = stdout.toString().split('\n');
+ lines.forEach(function (line) {
+ if (line.indexOf(':') != -1) {
+ if (line.toLowerCase().indexOf('hardware') != -1) result.model = line.split(':')[1].trim();
+ if (line.toLowerCase().indexOf('revision') != -1) result.version = line.split(':')[1].trim();
+ if (line.toLowerCase().indexOf('serial') != -1) result.serial = line.split(':')[1].trim();
+ }
+ });
+ if (result.model == 'BCM2709') {
+ result.manufacturer = 'Raspberry Pi Foundation';
+ result.model = result.model + ' - Pi 2 Model B';
+ if (['a01041', 'a21041'].indexOf(result.version) >= 0) {
+ result.version = result.version + ' - Rev. 1.1'
+ }
+ }
+ if (result.model == 'BCM2708') {
+ result.manufacturer = 'Raspberry Pi Foundation';
+ if (['0002', '0003'].indexOf(result.version) >= 0) {
+ result.model = result.model + ' - Pi Model B';
+ result.version = result.version + ' - Rev 1.0';
+ }
+ if (['0007', '0008', '0009'].indexOf(result.version) >= 0) {
+ result.model = result.model + ' - Pi Model A';
+ result.version = result.version + ' - Rev 2.0';
+ }
+ if (['0004', '0005', '0006', '000d', '000e', '000f'].indexOf(result.version) >= 0) {
+ result.model = result.model + ' - Pi Model B';
+ result.version = result.version + ' - Rev 2.0';
+ }
+ if (['0012'].indexOf(result.version) >= 0) {
+ result.model = result.model + ' - Pi Model A+';
+ result.version = result.version + ' - Rev 1.0';
+ }
+ if (['0010'].indexOf(result.version) >= 0) {
+ result.model = result.model + ' - Pi Model B+';
+ result.version = result.version + ' - Rev 1.0';
+ }
+ if (['0013'].indexOf(result.version) >= 0) {
+ result.model = result.model + ' - Pi Model B+';
+ result.version = result.version + ' - Rev 1.2';
+ }
+ }
+ }
+ })
+ }
+ }
+ if (callback) { callback(result) }
+ resolve(result);
+ })
+ }
+ if (_darwin) {
+ exec("ioreg -c IOPlatformExpertDevice -d 2", function (error, stdout) {
+ if (!error) {
+ var lines = stdout.toString().split('\n');
+ lines.forEach(function (line) {
+ line = line.replace(/[<>"]/g, "");
+ if (line.indexOf('=') != -1) {
+ if (line.toLowerCase().indexOf('manufacturer') != -1) result.manufacturer = line.split('=')[1].trim();
+ if (line.toLowerCase().indexOf('model') != -1) result.model = line.split('=')[1].trim();
+ if (line.toLowerCase().indexOf('version') != -1) result.version = line.split('=')[1].trim();
+ if (line.toLowerCase().indexOf('ioplatformserialnumber') != -1) result.serial = line.split('=')[1].trim();
+ if (line.toLowerCase().indexOf('ioplatformuuid') != -1) result.uuid = line.split('=')[1].trim();
+ }
+ });
+ }
+ if (callback) { callback(result) }
+ resolve(result);
+ })
+ }
+ });
+ });
}
exports.system = system;
@@ -228,7 +250,7 @@ exports.system = system;
// ----------------------------------------------------------------------------------
function version() {
- return lib_version;
+ return lib_version;
}
exports.version = version;
@@ -241,10 +263,10 @@ exports.version = version;
// Get current time and OS uptime
function time() {
- return {
- current : Date.now(),
- uptime : os.uptime()
- };
+ return {
+ current: Date.now(),
+ uptime: os.uptime()
+ };
}
exports.time = time;
@@ -253,35 +275,36 @@ exports.time = time;
// Get logo filename of OS distribution
function getLogoFile(distro) {
- var result = 'linux';
- if (distro.toLowerCase().indexOf('mac os') != -1) { result = 'apple' } else
- if (distro.toLowerCase().indexOf('arch') != -1) { result = 'arch' } else
- if (distro.toLowerCase().indexOf('centos') != -1) { result = 'centos' } else
- if (distro.toLowerCase().indexOf('coreos') != -1) { result = 'coreos' } else
- if (distro.toLowerCase().indexOf('debian') != -1) { result = 'debian' } else
- if (distro.toLowerCase().indexOf('elementary') != -1) { result = 'elementary' } else
- if (distro.toLowerCase().indexOf('fedora') != -1) { result = 'fedora' } else
- if (distro.toLowerCase().indexOf('gentoo') != -1) { result = 'gentoo' } else
- if (distro.toLowerCase().indexOf('mageia') != -1) { result = 'mageia' } else
- if (distro.toLowerCase().indexOf('mandriva') != -1) { result = 'mandriva' } else
- if (distro.toLowerCase().indexOf('manjaro') != -1) { result = 'manjaro' } else
- if (distro.toLowerCase().indexOf('mint') != -1) { result = 'mint' } else
- if (distro.toLowerCase().indexOf('openbsd') != -1) { result = 'openbsd' } else
- if (distro.toLowerCase().indexOf('opensuse') != -1) { result = 'opensuse' } else
- if (distro.toLowerCase().indexOf('pclinuxos') != -1) { result = 'pclinuxos' } else
- if (distro.toLowerCase().indexOf('puppy') != -1) { result = 'puppy' } else
- if (distro.toLowerCase().indexOf('raspbian') != -1) { result = 'raspbian' } else
- if (distro.toLowerCase().indexOf('reactos') != -1) { result = 'reactos' } else
- if (distro.toLowerCase().indexOf('redhat') != -1) { result = 'redhat' } else
- if (distro.toLowerCase().indexOf('slackware') != -1) { result = 'slackware' } else
- if (distro.toLowerCase().indexOf('sugar') != -1) { result = 'sugar' } else
- if (distro.toLowerCase().indexOf('steam') != -1) { result = 'steam' } else
- if (distro.toLowerCase().indexOf('suse') != -1) { result = 'suse' } else
- if (distro.toLowerCase().indexOf('mate') != -1) { result = 'ubuntu-mate' } else
- if (distro.toLowerCase().indexOf('lubuntu') != -1) { result = 'lubuntu' } else
- if (distro.toLowerCase().indexOf('xubuntu') != -1) { result = 'xubuntu' } else
- if (distro.toLowerCase().indexOf('ubuntu') != -1) { result = 'ubuntu' }
- return result;
+ distro = distro.toLowerCase();
+ let result = 'linux';
+ if (distro.indexOf('mac os') != -1) { result = 'apple' }
+ else if (distro.indexOf('arch') != -1) { result = 'arch' }
+ else if (distro.indexOf('centos') != -1) { result = 'centos' }
+ else if (distro.indexOf('coreos') != -1) { result = 'coreos' }
+ else if (distro.indexOf('debian') != -1) { result = 'debian' }
+ else if (distro.indexOf('elementary') != -1) { result = 'elementary' }
+ else if (distro.indexOf('fedora') != -1) { result = 'fedora' }
+ else if (distro.indexOf('gentoo') != -1) { result = 'gentoo' }
+ else if (distro.indexOf('mageia') != -1) { result = 'mageia' }
+ else if (distro.indexOf('mandriva') != -1) { result = 'mandriva' }
+ else if (distro.indexOf('manjaro') != -1) { result = 'manjaro' }
+ else if (distro.indexOf('mint') != -1) { result = 'mint' }
+ else if (distro.indexOf('openbsd') != -1) { result = 'openbsd' }
+ else if (distro.indexOf('opensuse') != -1) { result = 'opensuse' }
+ else if (distro.indexOf('pclinuxos') != -1) { result = 'pclinuxos' }
+ else if (distro.indexOf('puppy') != -1) { result = 'puppy' }
+ else if (distro.indexOf('raspbian') != -1) { result = 'raspbian' }
+ else if (distro.indexOf('reactos') != -1) { result = 'reactos' }
+ else if (distro.indexOf('redhat') != -1) { result = 'redhat' }
+ else if (distro.indexOf('slackware') != -1) { result = 'slackware' }
+ else if (distro.indexOf('sugar') != -1) { result = 'sugar' }
+ else if (distro.indexOf('steam') != -1) { result = 'steam' }
+ else if (distro.indexOf('suse') != -1) { result = 'suse' }
+ else if (distro.indexOf('mate') != -1) { result = 'ubuntu-mate' }
+ else if (distro.indexOf('lubuntu') != -1) { result = 'lubuntu' }
+ else if (distro.indexOf('xubuntu') != -1) { result = 'xubuntu' }
+ else if (distro.indexOf('ubuntu') != -1) { result = 'ubuntu' }
+ return result;
}
// --------------------------
@@ -289,54 +312,62 @@ function getLogoFile(distro) {
function osInfo(callback) {
- if (_windows) {
- callback(NOT_SUPPORTED);
- }
+ return new Promise((resolve, reject) => {
+ process.nextTick(() => {
+ if (_windows) {
+ let error = new Error(NOT_SUPPORTED);
+ if (callback) { callback(NOT_SUPPORTED) }
+ reject(error);
+ }
- var result = {
+ var result = {
- platform : _platform,
- distro : 'unknown',
- release : 'unknown',
- codename : '',
- kernel : os.release(),
- arch : os.arch(),
- hostname : os.hostname(),
- logofile : ''
- };
+ platform: _platform,
+ distro: 'unknown',
+ release: 'unknown',
+ codename: '',
+ kernel: os.release(),
+ arch: os.arch(),
+ hostname: os.hostname(),
+ logofile: ''
+ };
- if (_linux) {
+ if (_linux) {
- exec("cat /etc/*-release", function(error, stdout) {
- if (!error) {
- var release = {};
- var lines = stdout.toString().split('\n');
- lines.forEach(function(line) {
- if (line.indexOf('=') != -1) {
- release[line.split('=')[0].trim().toUpperCase()] = line.split('=')[1].trim();
- }
- });
- result.distro = (release.DISTRIB_ID || release.NAME || 'unknown').replace(/"/g, '');
- result.logofile = getLogoFile(result.distro);
- result.release = (release.DISTRIB_RELEASE || release.VERSION_ID || 'unknown').replace(/"/g, '');
- result.codename = (release.DISTRIB_CODENAME || '').replace(/"/g, '');
- }
- callback(result);
- })
- }
- if (_darwin) {
- exec("sw_vers", function(error, stdout) {
- var lines = stdout.toString().split('\n');
- lines.forEach(function(line) {
- if (line.indexOf('ProductName') != -1) {
- result.distro = line.split(':')[1].trim();
- result.logofile = getLogoFile(result.distro);
- }
- if (line.indexOf('ProductVersion') != -1) result.release = line.split(':')[1].trim();
- });
- callback(result);
- })
- }
+ exec("cat /etc/*-release", function (error, stdout) {
+ if (!error) {
+ var release = {};
+ var lines = stdout.toString().split('\n');
+ lines.forEach(function (line) {
+ if (line.indexOf('=') != -1) {
+ release[line.split('=')[0].trim().toUpperCase()] = line.split('=')[1].trim();
+ }
+ });
+ result.distro = (release.DISTRIB_ID || release.NAME || 'unknown').replace(/"/g, '');
+ result.logofile = getLogoFile(result.distro);
+ result.release = (release.DISTRIB_RELEASE || release.VERSION_ID || 'unknown').replace(/"/g, '');
+ result.codename = (release.DISTRIB_CODENAME || '').replace(/"/g, '');
+ }
+ if (callback) { callback(result) }
+ resolve(result);
+ })
+ }
+ if (_darwin) {
+ exec("sw_vers", function (error, stdout) {
+ var lines = stdout.toString().split('\n');
+ lines.forEach(function (line) {
+ if (line.indexOf('ProductName') != -1) {
+ result.distro = line.split(':')[1].trim();
+ result.logofile = getLogoFile(result.distro);
+ }
+ if (line.indexOf('ProductVersion') != -1) result.release = line.split(':')[1].trim();
+ });
+ if (callback) { callback(result) }
+ resolve(result);
+ })
+ }
+ });
+ });
}
exports.osInfo = osInfo;
@@ -346,89 +377,119 @@ exports.osInfo = osInfo;
// ----------------------------------------------------------------------------------
function cpuBrandManufacturer(res) {
- res.brand = res.brand.replace(/\(R\)+/g, "®");
- res.brand = res.brand.replace(/\(TM\)+/g, "™");
- res.brand = res.brand.replace(/\(C\)+/g, "©");
- res.brand = res.brand.replace(/CPU+/g, "").trim();
- res.manufacturer = res.brand.split(' ')[0];
- var parts = res.brand.split(' ');
- parts.shift();
- res.brand = parts.join(' ');
- return res;
+ res.brand = res.brand.replace(/\(R\)+/g, "®");
+ res.brand = res.brand.replace(/\(TM\)+/g, "™");
+ res.brand = res.brand.replace(/\(C\)+/g, "©");
+ res.brand = res.brand.replace(/CPU+/g, "").trim();
+ res.manufacturer = res.brand.split(' ')[0];
+
+ let parts = res.brand.split(' ');
+ parts.shift();
+ res.brand = parts.join(' ');
+ return res;
}
// --------------------------
// CPU - brand, speed
-function getCpu(callback) {
+function getCpu() {
- var result = {
- manufacturer : 'unknown',
- brand : 'unknown',
- speed : '0.00',
- cores : _cores
- };
- if (_darwin) {
- exec("sysctl -n machdep.cpu.brand_string", function(error, stdout) {
- if (!error) {
- var lines = stdout.toString().split('\n');
- result.brand = lines[0].split('@')[0].trim();
- result.speed = lines[0].split('@')[1].trim();
- result.speed = parseFloat(result.speed.replace(/GHz+/g, ""));
- _cpu_speed = result.speed;
- }
- result = cpuBrandManufacturer(result);
- callback(result);
- });
- }
- if (_linux) {
- exec("cat /proc/cpuinfo | grep 'model name'", function(error, stdout) {
- if (!error) {
- var lines = stdout.toString().split('\n');
- var line = lines[0].split(':')[1];
- result.brand = line.split('@')[0].trim();
- result.speed = line.split('@')[1] ? parseFloat(line.split('@')[1].trim()).toFixed(2) : '0.00';
- if (result.speed == '0.00') {
- var current = getCpuCurrentSpeedSync();
- if (current != '0.00') result.speed = current;
- }
- _cpu_speed = result.speed;
- }
- result = cpuBrandManufacturer(result);
- callback(result);
- })
- }
+ return new Promise((resolve, reject) => {
+ process.nextTick(() => {
+ if (_windows) {
+ let error = new Error(NOT_SUPPORTED);
+ if (callback) { callback(NOT_SUPPORTED) }
+ reject(error);
+ }
+
+ var result = {
+ manufacturer: 'unknown',
+ brand: 'unknown',
+ speed: '0.00',
+ cores: _cores
+ };
+ if (_darwin) {
+ exec("sysctl -n machdep.cpu.brand_string", function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+ result.brand = lines[0].split('@')[0].trim();
+ result.speed = lines[0].split('@')[1].trim();
+ result.speed = parseFloat(result.speed.replace(/GHz+/g, ""));
+ _cpu_speed = result.speed;
+ }
+ result = cpuBrandManufacturer(result);
+ resolve(result);
+ });
+ }
+ if (_linux) {
+ exec("cat /proc/cpuinfo | grep 'model name'", function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+ let line = lines[0].split(':')[1];
+ result.brand = line.split('@')[0].trim();
+ result.speed = line.split('@')[1] ? parseFloat(line.split('@')[1].trim()).toFixed(2) : '0.00';
+ if (result.speed == '0.00') {
+ let current = getCpuCurrentSpeedSync();
+ if (current != '0.00') result.speed = current;
+ }
+ _cpu_speed = result.speed;
+ }
+ result = cpuBrandManufacturer(result);
+ resolve(result);
+ })
+ }
+ });
+ });
}
// --------------------------
// CPU - Processor cores
-function cores(callback) {
- exec("grep -c ^processor /proc/cpuinfo 2>/dev/null || sysctl -n hw.ncpu", function(error, stdout) {
- var result = {cores: 1};
- if (!error) {
- result.cores = parseInt(stdout.toString());
- _cores = result.cores;
- }
- if (callback) callback(result);
- })
+function cores() {
+
+ return new Promise((resolve, reject) => {
+ process.nextTick(() => {
+ if (_windows) {
+ let error = new Error(NOT_SUPPORTED);
+ if (callback) { callback(NOT_SUPPORTED) }
+ reject(error);
+ }
+ let result = os.cpus().length;
+ resolve(result);
+ });
+ });
}
// --------------------------
// CPU - Processor Data
function cpu(callback) {
- if (_windows) {
- callback(NOT_SUPPORTED);
- }
- if (_cores == 0) {
- cores(function() {
- getCpu(callback)
- })
- } else {
- getCpu(callback)
- }
+ return new Promise((resolve, reject) => {
+ process.nextTick(() => {
+ if (_windows) {
+ let error = new Error(NOT_SUPPORTED);
+ if (callback) { callback(NOT_SUPPORTED) }
+ reject(error);
+ }
+
+ if (_cores == 0) {
+ cores()
+ .then(data => {
+ _cores = data;
+ getCpu().then(result => {
+ if (callback) { callback(result) }
+ resolve(result);
+ })
+ })
+ } else {
+ getCpu().then(result => {
+ if (callback) { callback(result) }
+ resolve(result);
+ })
+ }
+ });
+ });
}
exports.cpu = cpu;
@@ -437,40 +498,52 @@ exports.cpu = cpu;
// CPU - current speed - in GHz
function getCpuCurrentSpeedSync() {
- var output = "";
- var result = "0.00";
- if (fs.existsSync("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq")) {
- output = fs.readFileSync("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq").toString();
- } else if (fs.existsSync("/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq")) {
- output = fs.readFileSync("/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq").toString();
- }
- if (output.trim()) {
- var lines = output.toString().split('\n');
- result = parseFloat((parseInt(lines[0]) / 1000 / 1000).toFixed(2));
- }
- return result;
+
+ let cpus = os.cpus();
+ let minFreq = 999999999;
+ let maxFreq = 0;
+ let avgFreq = 0;
+
+ if (cpus.length) {
+ for (let i in cpus) {
+ if (cpus.hasOwnProperty(i)) {
+ avgFreq = avgFreq + cpus[i].speed;
+ if (cpus[i].speed > maxFreq) maxFreq = cpus[i].speed;
+ if (cpus[i].speed < minFreq) minFreq = cpus[i].speed;
+ }
+ }
+ avgFreq = avgFreq / cpus.length;
+ return {
+ min: parseFloat((minFreq / 1000).toFixed(2)),
+ max: parseFloat((maxFreq / 1000).toFixed(2)),
+ avg: parseFloat((avgFreq / 1000).toFixed(2))
+ }
+ } else {
+ return {
+ min: 0,
+ max: 0,
+ avg: 0
+ }
+ }
}
function cpuCurrentspeed(callback) {
- if (_windows) {
- callback(NOT_SUPPORTED);
- }
- var result = _cpu_speed;
- if (_darwin) {
- exec("sysctl -n hw.cpufrequency", function(error, stdout) {
- if (!error) {
- var lines = stdout.toString().split('\n');
- result = parseFloat((parseInt(lines[0]) / 1000 / 1000 / 1000).toFixed(2));
- }
- callback(result);
- });
- }
- if (_linux) {
- result = getCpuCurrentSpeedSync();
- if (result == '0.00' && _cpu_speed != '0.00') result = _cpu_speed;
- callback(result);
- }
+ return new Promise((resolve, reject) => {
+ process.nextTick(() => {
+ if (_windows) {
+ let error = new Error(NOT_SUPPORTED);
+ if (callback) { callback(NOT_SUPPORTED) }
+ reject(error);
+ }
+
+ let result = getCpuCurrentSpeedSync();
+ if (result == 0 && _cpu_speed != '0.00') result = parseFloat(_cpu_speed);
+
+ if (callback) { callback(result) }
+ resolve(result);
+ });
+ });
}
exports.cpuCurrentspeed = cpuCurrentspeed;
@@ -480,52 +553,62 @@ exports.cpuCurrentspeed = cpuCurrentspeed;
// if sensors are installed
function cpuTemperature(callback) {
- if (_windows) {
- callback(NOT_SUPPORTED);
- }
- var result = {
- main : -1.0,
- cores : [],
- max : -1.0
- };
- if (_linux) {
- var regex = /\+([^°]*)/g;
- exec("sensors", function(error, stdout) {
- if (!error) {
- var lines = stdout.toString().split('\n');
- lines.forEach(function(line) {
- var temps = line.match(regex);
- if (line.split(':')[0].toUpperCase().indexOf('PHYSICAL') != -1) {
- result.main = parseFloat(temps);
- }
- if (line.split(':')[0].toUpperCase().indexOf('CORE ') != -1) {
- result.cores.push(parseFloat(temps));
- }
- });
- if (result.cores.length > 0) {
- var maxtmp = Math.max.apply(Math, result.cores);
- result.max = (maxtmp > result.main) ? maxtmp : result.main;
- }
- callback(result)
- } else {
- exec("/opt/vc/bin/vcgencmd measure_temp", function(error, stdout) {
- if (!error) {
- var lines = stdout.toString().split('\n');
- if (lines.length > 0 && lines[0].indexOf('=')) {
- result.main = parseFloat(lines[0].split("=")[1]);
- result.max = result.main
- }
- }
- callback(result)
- });
+ return new Promise((resolve, reject) => {
+ process.nextTick(() => {
+ if (_windows) {
+ let error = new Error(NOT_SUPPORTED);
+ if (callback) { callback(NOT_SUPPORTED) }
+ reject(error);
+ }
- }
- });
- }
- if (_darwin) {
- callback(result)
- }
+ var result = {
+ main: -1.0,
+ cores: [],
+ max: -1.0
+ };
+ if (_linux) {
+ exec("sensors", function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+ lines.forEach(function (line) {
+ let regex = /\+([^°]*)/g;
+ let temps = line.match(regex);
+ if (line.split(':')[0].toUpperCase().indexOf('PHYSICAL') != -1) {
+ result.main = parseFloat(temps);
+ }
+ if (line.split(':')[0].toUpperCase().indexOf('CORE ') != -1) {
+ result.cores.push(parseFloat(temps));
+ }
+ });
+ if (result.cores.length > 0) {
+ let maxtmp = Math.max.apply(Math, result.cores);
+ result.max = (maxtmp > result.main) ? maxtmp : result.main;
+ }
+ if (callback) { callback(result) }
+ resolve(result);
+ } else {
+ exec("/opt/vc/bin/vcgencmd measure_temp", function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+ if (lines.length > 0 && lines[0].indexOf('=')) {
+ result.main = parseFloat(lines[0].split("=")[1]);
+ result.max = result.main
+ }
+ }
+ if (callback) { callback(result) }
+ resolve(result);
+ });
+
+ }
+ });
+ }
+ if (_darwin) {
+ if (callback) { callback(result) }
+ resolve(result);
+ }
+ });
+ });
}
exports.cpuTemperature = cpuTemperature;
@@ -534,79 +617,138 @@ exports.cpuTemperature = cpuTemperature;
// 5. Memory
// ----------------------------------------------------------------------------------
-// | R A M | H D |
-// |_________________|__________________________| | |
-// | active buffers/cache | | |
-// |____________________________________________|___________|_________|______________|
-// | used free | used free |
-// |________________________________________________________|________________________|
-// | total | swap |
-// | | |
+// | R A M | H D |
+// |______________________|_________________________| | |
+// | active buffers/cache | | |
+// |________________________________________________|___________|_________|______________|
+// | used free | used free |
+// |____________________________________________________________|________________________|
+// | total | swap |
+// | | |
+
+// free (older versions)
+// ----------------------------------
+// # free
+// total used free shared buffers cached
+// Mem: 16038 (1) 15653 (2) 384 (3) 0 (4) 236 (5) 14788 (6)
+// -/+ buffers/cache: 628 (7) 15409 (8)
+// Swap: 16371 83 16288
+//
+// |------------------------------------------------------------|
+// | R A M |
+// |______________________|_____________________________________|
+// | active (2-(5+6) = 7) | available (3+5+6 = 8) |
+// |______________________|_________________________|___________|
+// | active | buffers/cache (5+6) | |
+// |________________________________________________|___________|
+// | used (2) | free (3) |
+// |____________________________________________________________|
+// | total (1) |
+// |____________________________________________________________|
+
+//
+// free (since free von procps-ng 3.3.10)
+// ----------------------------------
+// # free
+// total used free shared buffers/cache available
+// Mem: 16038 (1) 628 (2) 386 (3) 0 (4) 15024 (5) 14788 (6)
+// Swap: 16371 83 16288
+//
+// |------------------------------------------------------------|
+// | R A M |
+// |______________________|_____________________________________|
+// | | available (6) estimated |
+// |______________________|_________________________|___________|
+// | active (2) | buffers/cache (5) | free (3) |
+// |________________________________________________|___________|
+// | total (1) |
+// |____________________________________________________________|
+//
+// Reference: http://www.software-architect.net/blog/article/date/2015/06/12/-826c6e5052.html
function mem(callback) {
- if (_windows) {
- callback(NOT_SUPPORTED);
- }
- var result = {
- total : os.totalmem(),
- free : os.freemem(),
- used : os.totalmem() - os.freemem(),
+ return new Promise((resolve, reject) => {
+ process.nextTick(() => {
+ if (_windows) {
+ let error = new Error(NOT_SUPPORTED);
+ if (callback) { callback(NOT_SUPPORTED) }
+ reject(error);
+ }
- active : os.totalmem() - os.freemem(),
- buffcache : 0,
+ var result = {
+ total: os.totalmem(),
+ free: os.freemem(),
+ used: os.totalmem() - os.freemem(),
- swaptotal : 0,
- swapused : 0,
- swapfree : 0
- };
+ active: os.totalmem() - os.freemem(), // temporarily (fallback)
+ available: os.freemem(), // temporarily (fallback)
+ buffcache: 0,
- if (_linux) {
- exec("free -b", function(error, stdout) {
- if (!error) {
- var lines = stdout.toString().split('\n');
+ swaptotal: 0,
+ swapused: 0,
+ swapfree: 0
+ };
- var mem = lines[1].replace(/ +/g, " ").split(' ');
- result.total = parseInt(mem[1]);
- result.free = parseInt(mem[3]);
- result.buffcache = parseInt(mem[5]) + parseInt(mem[6]);
- result.active = result.total - result.free - result.buffcache;
+ if (_linux) {
+ exec("free -b", function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().split('\n');
- mem = lines[3].replace(/ +/g, " ").split(' ');
- result.swaptotal = parseInt(mem[1]);
- result.swapfree = parseInt(mem[3]);
- result.swapused = parseInt(mem[2]);
+ let mem = lines[1].replace(/ +/g, " ").split(' ');
+ result.total = parseInt(mem[1]);
+ result.free = parseInt(mem[3]);
- }
- callback(result);
- });
- }
- if (_darwin) {
- exec("vm_stat | grep 'Pages active'", function(error, stdout) {
- if (!error) {
- var lines = stdout.toString().split('\n');
+ if (lines.length === 4) { // free (since free von procps-ng 3.3.10)
+ result.buffcache = parseInt(mem[5]);
+ result.available = parseInt(mem[6]);
+ mem = lines[2].replace(/ +/g, " ").split(' ');
+ } else { // free (older versions)
+ result.buffcache = parseInt(mem[5]) + parseInt(mem[6]);
+ result.available = result.free + result.buffcache;
+ mem = lines[3].replace(/ +/g, " ").split(' ');
+ }
+ result.active = result.total - result.free - result.buffcache;
- result.active = parseInt(lines[0].split(':')[1]) * 4096;
- result.buffcache = result.used - result.active;
- }
- exec("sysctl -n vm.swapusage", function(error, stdout) {
- if (!error) {
- var lines = stdout.toString().split('\n');
- if (lines.length > 0) {
- var line = lines[0].replace(/,/g, ".").replace(/M/g, "");
- line = line.trim().split(' ');
- for (var i = 0; i < line.length; i++) {
- if(line[i].toLowerCase().indexOf('total') != -1) result.swaptotal = parseFloat(line[i].split('=')[1].trim()) * 1024 * 1024;
- if(line[i].toLowerCase().indexOf('used') != -1) result.swapused = parseFloat(line[i].split('=')[1].trim()) * 1024 * 1024;
- if(line[i].toLowerCase().indexOf('free') != -1) result.swapfree = parseFloat(line[i].split('=')[1].trim()) * 1024 * 1024;
+ result.swaptotal = parseInt(mem[1]);
+ result.swapfree = parseInt(mem[3]);
+ result.swapused = parseInt(mem[2]);
- }
- }
- }
- callback(result);
- });
- });
- }
+ }
+ if (callback) { callback(result) }
+ resolve(result);
+ });
+ }
+ if (_darwin) {
+ exec("vm_stat | grep 'Pages active'", function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+
+ result.active = parseInt(lines[0].split(':')[1]) * 4096;
+ result.buffcache = result.used - result.active;
+ result.available = result.free + result.buffcache;
+ }
+ exec("sysctl -n vm.swapusage", function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+ if (lines.length > 0) {
+ let line = lines[0].replace(/,/g, ".").replace(/M/g, "");
+ line = line.trim().split(' ');
+ for (let i = 0; i < line.length; i++) {
+ if (line[i].toLowerCase().indexOf('total') != -1) result.swaptotal = parseFloat(line[i].split('=')[1].trim()) * 1024 * 1024;
+ if (line[i].toLowerCase().indexOf('used') != -1) result.swapused = parseFloat(line[i].split('=')[1].trim()) * 1024 * 1024;
+ if (line[i].toLowerCase().indexOf('free') != -1) result.swapfree = parseFloat(line[i].split('=')[1].trim()) * 1024 * 1024;
+
+ }
+ }
+ }
+ if (callback) { callback(result) }
+ resolve(result);
+ });
+ });
+ }
+ });
+ });
}
exports.mem = mem;
@@ -619,30 +761,38 @@ exports.mem = mem;
// FS - devices
function fsSize(callback) {
- if (_windows) {
- callback(NOT_SUPPORTED);
- }
- exec("df -lk | grep ^/", function(error, stdout) {
- var data = [];
- if (!error) {
- var lines = stdout.toString().split('\n');
- //lines.splice(0, 1);
- lines.forEach(function (line) {
- if (line != '') {
- line = line.replace(/ +/g, " ").split(' ');
- data.push({
- 'fs': line[0],
- 'size': parseInt(line[1]) * 1024,
- 'used': parseInt(line[2]) * 1024,
- 'use': parseFloat((100.0 * line[2] / line[1]).toFixed(2)),
- 'mount': line[line.length - 1]
- })
- }
- });
- }
- callback(data)
- });
+ return new Promise((resolve, reject) => {
+ process.nextTick(() => {
+ if (_windows) {
+ let error = new Error(NOT_SUPPORTED);
+ if (callback) { callback(NOT_SUPPORTED) }
+ reject(error);
+ }
+
+ exec("df -lk | grep ^/", function (error, stdout) {
+ let data = [];
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+ //lines.splice(0, 1);
+ lines.forEach(function (line) {
+ if (line != '') {
+ line = line.replace(/ +/g, " ").split(' ');
+ data.push({
+ 'fs': line[0],
+ 'size': parseInt(line[1]) * 1024,
+ 'used': parseInt(line[2]) * 1024,
+ 'use': parseFloat((100.0 * line[2] / line[1]).toFixed(2)),
+ 'mount': line[line.length - 1]
+ })
+ }
+ });
+ }
+ if (callback) { callback(data) }
+ resolve(data);
+ });
+ });
+ });
}
exports.fsSize = fsSize;
@@ -651,132 +801,273 @@ exports.fsSize = fsSize;
// FS - speed
function fsStats(callback) {
- if (_windows) {
- callback(NOT_SUPPORTED);
- }
- var result = {
- rx : -1,
- wx : -1,
- rx_sec : -1,
- wx_sec : -1
- };
- var bytes_read = 0;
- var bytes_write = 0;
- var lines;
+ return new Promise((resolve, reject) => {
+ process.nextTick(() => {
+ if (_windows) {
+ let error = new Error(NOT_SUPPORTED);
+ if (callback) { callback(NOT_SUPPORTED) }
+ reject(error);
+ }
- if (_linux) {
+ var result = {
+ rx: 0,
+ wx: 0,
+ tx: 0,
+ rx_sec: -1,
+ wx_sec: -1,
+ tx_sec: -1,
+ ms: 0
+ };
+
+ if (_linux) {
// exec("df -k | grep /dev/", function(error, stdout) {
- exec("lsblk | grep /", function(error, stdout) {
- if (!error) {
- lines = stdout.toString().split('\n');
- var fs_filter = [];
- lines.forEach(function (line) {
- if (line != '') {
- line = line.replace(/[├─│└]+/g, "").trim().split(' ');
- if (fs_filter.indexOf(line[0]) == -1) fs_filter.push(line[0])
- }
- });
+ exec("lsblk | grep /", function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+ let fs_filter = [];
+ lines.forEach(function (line) {
+ if (line != '') {
+ line = line.replace(/[├─│└]+/g, "").trim().split(' ');
+ if (fs_filter.indexOf(line[0]) == -1) fs_filter.push(line[0])
+ }
+ });
- var output = fs_filter.join('|');
- exec("cat /proc/diskstats | egrep '" + output + "'", function (error, stdout) {
- if (!error) {
- lines = stdout.toString().split('\n');
- lines.forEach(function (line) {
- line = line.trim();
- if (line != '') {
- line = line.replace(/ +/g, " ").split(' ');
+ let output = fs_filter.join('|');
+ exec("cat /proc/diskstats | egrep '" + output + "'", function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+ lines.forEach(function (line) {
+ line = line.trim();
+ if (line != '') {
+ line = line.replace(/ +/g, " ").split(' ');
- bytes_read = bytes_read + parseInt(line[5]) * 512;
- bytes_write = bytes_write + parseInt(line[9]) * 512;
- }
- });
- if (_fs_speed && _fs_speed.ms) {
- var ms = Date.now() - _fs_speed.ms;
- result.rx = bytes_read;
- result.wx = bytes_write;
- result.rx_sec = (bytes_read - _fs_speed.bytes_read) / (ms / 1000);
- result.wx_sec = (bytes_write - _fs_speed.bytes_write) / (ms / 1000);
- } else {
- result.rx = bytes_read;
- result.wx = bytes_write;
- result.rx_sec = 0;
- result.wx_sec = 0;
- }
- _fs_speed.bytes_read = bytes_read;
- _fs_speed.bytes_write = bytes_write;
- _fs_speed.bytes_overall = bytes_read + bytes_write;
- _fs_speed.ms = Date.now();
- }
- callback(result);
- })
- } else callback(result);
- })
- }
- if (_darwin) {
- exec("ioreg -c IOBlockStorageDriver -k Statistics -r -w0 | sed -n '/IOBlockStorageDriver/,/Statistics/p' | grep 'Statistics' | tr -d [:alpha:] | tr -d [:punct:] | awk '{print $3, $10}'", function(error, stdout) {
- if (!error) {
- lines = stdout.toString().split('\n');
- lines.forEach(function (line) {
- line = line.trim();
- if (line != '') {
- line = line.split(' ');
+ result.rx += parseInt(line[5]) * 512;
+ result.wx += parseInt(line[9]) * 512;
+ }
+ });
+ result.tx = result.rx + result.wx;
+ if (_fs_speed && _fs_speed.ms) {
+ result.ms = Date.now() - _fs_speed.ms;
+ result.rx_sec = (result.rx - _fs_speed.bytes_read) / (result.ms / 1000);
+ result.wx_sec = (result.wx - _fs_speed.bytes_write) / (result.ms / 1000);
+ result.tx_sec = result.rx_sec + result.wx_sec;
+ } else {
+ result.rx_sec = -1;
+ result.wx_sec = -1;
+ result.tx_sec = -1;
+ }
+ _fs_speed.bytes_read = result.rx;
+ _fs_speed.bytes_write = result.wx;
+ _fs_speed.bytes_overall = result.rx + result.wx;
+ _fs_speed.ms = Date.now();
+ }
+ if (callback) { callback(result) }
+ resolve(result);
+ })
+ } else {
+ if (callback) { callback(result) }
+ resolve(result);
+ }
+ })
+ }
+ if (_darwin) {
+ exec("ioreg -c IOBlockStorageDriver -k Statistics -r -w0 | sed -n '/IOBlockStorageDriver/,/Statistics/p' | grep 'Statistics' | tr -d [:alpha:] | tr -d [:punct:] | awk '{print $3, $10}'", function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+ lines.forEach(function (line) {
+ line = line.trim();
+ if (line != '') {
+ line = line.split(' ');
- bytes_read = bytes_read + parseInt(line[0]);
- bytes_write = bytes_write + parseInt(line[1]);
- }
- });
-
- if (_fs_speed && _fs_speed.ms) {
- var ms = Date.now() - _fs_speed.ms;
- result.rx = bytes_read;
- result.wx = bytes_write;
- result.rx_sec = (bytes_read - _fs_speed.bytes_read) / (ms / 1000);
- result.wx_sec = (bytes_write - _fs_speed.bytes_write) / (ms / 1000);
- } else {
- result.rx = bytes_read;
- result.wx = bytes_write;
- result.rx_sec = 0;
- result.wx_sec = 0;
- }
- _fs_speed.bytes_read = bytes_read;
- _fs_speed.bytes_write = bytes_write;
- _fs_speed.bytes_overall = bytes_read + bytes_write;
- _fs_speed.ms = Date.now();
- }
- callback(result)
- })
- }
+ result.rx += parseInt(line[0]);
+ result.wx += parseInt(line[1]);
+ }
+ });
+ result.tx = result.rx + result.wx;
+ if (_fs_speed && _fs_speed.ms) {
+ result.ms = Date.now() - _fs_speed.ms;
+ result.rx_sec = (result.rx - _fs_speed.bytes_read) / (result.ms / 1000);
+ result.wx_sec = (result.wx - _fs_speed.bytes_write) / (result.ms / 1000);
+ result.tx_sec = result.rx_sec + result.wx_sec;
+ } else {
+ result.rx_sec = -1;
+ result.wx_sec = -1;
+ result.tx_sec = -1;
+ }
+ _fs_speed.bytes_read = result.rx;
+ _fs_speed.bytes_write = result.wx;
+ _fs_speed.bytes_overall = result.rx + result.wx;
+ _fs_speed.ms = Date.now();
+ }
+ if (callback) { callback(result) }
+ resolve(result);
+ })
+ }
+ });
+ });
}
exports.fsStats = fsStats;
+function disksIO(callback) {
+
+ return new Promise((resolve, reject) => {
+ process.nextTick(() => {
+ if (_windows) {
+ let error = new Error(NOT_SUPPORTED);
+ if (callback) { callback(NOT_SUPPORTED) }
+ reject(error);
+ }
+
+ var result = {
+ rIO: 0,
+ wIO: 0,
+ tIO: 0,
+ rIO_sec: -1,
+ wIO_sec: -1,
+ tIO_sec: -1,
+ ms: 0
+ };
+ if (_linux) {
+ // prints Block layer statistics for all mounted volumes
+ // var cmd = "for mount in `lsblk | grep / | sed -r 's/│ └─//' | cut -d ' ' -f 1`; do cat /sys/block/$mount/stat | sed -r 's/ +/;/g' | sed -r 's/^;//'; done";
+ // var cmd = "for mount in `lsblk | grep / | sed 's/[│└─├]//g' | awk '{$1=$1};1' | cut -d ' ' -f 1 | sort -u`; do cat /sys/block/$mount/stat | sed -r 's/ +/;/g' | sed -r 's/^;//'; done";
+ let cmd = "for mount in `lsblk | grep ' disk ' | sed 's/[│└─├]//g' | awk '{$1=$1};1' | cut -d ' ' -f 1 | sort -u`; do cat /sys/block/$mount/stat | sed -r 's/ +/;/g' | sed -r 's/^;//'; done";
+
+ exec(cmd, function (error, stdout) {
+ if (!error) {
+ let lines = stdout.split('\n');
+ lines.forEach(function (line) {
+ // ignore empty lines
+ if (!line) return;
+
+ // sum r/wIO of all disks to compute all disks IO
+ let stats = line.split(';');
+ result.rIO += parseInt(stats[0]);
+ result.wIO += parseInt(stats[4]);
+ });
+ result.tIO = result.rIO + result.wIO;
+ if (_disk_io && _disk_io.ms) {
+ result.ms = Date.now() - _disk_io.ms;
+ result.rIO_sec = (result.rIO - _disk_io.rIO) / (result.ms / 1000);
+ result.wIO_sec = (result.wIO - _disk_io.wIO) / (result.ms / 1000);
+ result.tIO_sec = result.rIO_sec + result.wIO_sec;
+ } else {
+ result.rIO_sec = -1;
+ result.wIO_sec = -1;
+ result.tIO_sec = -1;
+ }
+ _disk_io.rIO = result.rIO;
+ _disk_io.wIO = result.wIO;
+ _disk_io.tIO = result.tIO;
+ _disk_io.ms = Date.now();
+
+ if (callback) { callback(result) }
+ resolve(result);
+ } else {
+ if (callback) { callback(result) }
+ resolve(result);
+ }
+ });
+ }
+ if (_darwin) {
+ exec("ioreg -c IOBlockStorageDriver -k Statistics -r -w0 | sed -n '/IOBlockStorageDriver/,/Statistics/p' | grep 'Statistics' | tr -d [:alpha:] | tr -d [:punct:] | awk '{print $1, $11}'", function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+ lines.forEach(function (line) {
+ line = line.trim();
+ if (line != '') {
+ line = line.split(' ');
+
+ result.rIO += parseInt(line[0]);
+ result.wIO += parseInt(line[1]);
+ }
+ });
+
+ result.tIO = result.rIO + result.wIO;
+ if (_disk_io && _disk_io.ms) {
+ result.ms = Date.now() - _disk_io.ms;
+ result.rIOPS = (result.rIO - _disk_io.rIO) / (result.ms / 1000);
+ result.wIOPS = (result.wIO - _disk_io.wIO) / (result.ms / 1000);
+ result.tIOPS = result.rIOPS + result.wIOPS;
+ } else {
+ result.rIOPS = -1;
+ result.wIOPS = -1;
+ result.tIOPS = -1;
+ }
+ _disk_io.rIO = result.rIO;
+ _disk_io.wIO = result.wIO;
+ _disk_io.tIO = result.tIO;
+ _disk_io.ms = Date.now();
+ }
+ if (callback) { callback(result) }
+ resolve(result);
+ })
+ }
+ });
+ });
+}
+
+exports.disksIO = disksIO;
+
// ----------------------------------------------------------------------------------
// 7. Network
// ----------------------------------------------------------------------------------
+function getFirstExternalNetworkInterface() {
+
+ let ifacename = '';
+ let ifaces = os.networkInterfaces();
+
+ for (let dev in ifaces) {
+ if (ifaces.hasOwnProperty(dev)) {
+ ifaces[dev].forEach(function (details) {
+ if (details && details.internal == false) {
+ ifacename = ifacename || dev;
+ }
+ })
+ }
+ }
+ return ifacename;
+}
+
// --------------------------
// NET - interfaces
function networkInterfaces(callback) {
- var ifaces=os.networkInterfaces();
- var result = [];
- for (var dev in ifaces) {
- var ip4 = '';
- var ip6 = '';
- if (ifaces.hasOwnProperty(dev)) {
- ifaces[dev].forEach(function(details){
- if (details.family=='IPv4') {
- ip4 = details.address
- }
- if (details.family=='IPv6') {
- ip6 = details.address
- }
- });
- result.push({iface : dev, ip4 : ip4, ip6 : ip6})
- }
- }
- callback(result);
+
+ return new Promise((resolve, reject) => {
+ process.nextTick(() => {
+ if (_windows) {
+ let error = new Error(NOT_SUPPORTED);
+ if (callback) { callback(NOT_SUPPORTED) }
+ reject(error);
+ }
+
+ let ifaces = os.networkInterfaces();
+ let result = [];
+
+ for (let dev in ifaces) {
+ let ip4 = '';
+ let ip6 = '';
+ if (ifaces.hasOwnProperty(dev)) {
+ ifaces[dev].forEach(function (details) {
+ if (details.family == 'IPv4') {
+ ip4 = details.address
+ }
+ if (details.family == 'IPv6') {
+ ip6 = details.address
+ }
+ });
+ let internal = (ifaces[dev] && ifaces[dev][0]) ? ifaces[dev][0].internal : null;
+ result.push({ iface: dev, ip4: ip4, ip6: ip6, internal: internal })
+ }
+ }
+ if (callback) { callback(result) }
+ resolve(result);
+ });
+ });
}
exports.networkInterfaces = networkInterfaces;
@@ -785,96 +1076,114 @@ exports.networkInterfaces = networkInterfaces;
// NET - Speed
function calcNetworkSpeed(iface, rx, tx) {
- var rx_sec = -1;
- var tx_sec = -1;
- if (_network[iface]) {
- var ms = Date.now() - _network[iface].ms;
- rx_sec = (rx - _network[iface].rx) / (ms / 1000);
- tx_sec = (tx - _network[iface].tx) / (ms / 1000);
- } else {
- _network[iface] = {};
- }
- _network[iface].rx = rx;
- _network[iface].tx = tx;
- _network[iface].ms = Date.now();
- return ({
- rx_sec : rx_sec,
- tx_sec : tx_sec
- })
+ let rx_sec = -1;
+ let tx_sec = -1;
+ let ms = 0;
+ if (_network[iface] && _network[iface].ms) {
+ ms = Date.now() - _network[iface].ms;
+ rx_sec = (rx - _network[iface].rx) / (ms / 1000);
+ tx_sec = (tx - _network[iface].tx) / (ms / 1000);
+ } else {
+ _network[iface] = {};
+ }
+ _network[iface].rx = rx;
+ _network[iface].tx = tx;
+ _network[iface].ms = Date.now();
+ return ({
+ rx_sec: rx_sec,
+ tx_sec: tx_sec,
+ ms: ms
+ })
}
function networkStats(iface, callback) {
- // fallback - if only callback is given
- if (isFunction(iface) && !callback) {
- callback = iface;
- iface = '';
- }
- iface = iface || (_darwin ? 'en0' : 'eth0');
- if (_windows) {
- callback(NOT_SUPPORTED);
- }
+ // fallback - if only callback is given
+ if (isFunction(iface) && !callback) {
+ callback = iface;
+ iface = '';
+ }
- var result = {
- iface : iface,
- operstate : 'unknown',
- rx: 0,
- tx: 0,
- rx_sec : -1,
- tx_sec : -1
- };
+ return new Promise((resolve, reject) => {
+ process.nextTick(() => {
+ if (_windows) {
+ let error = new Error(NOT_SUPPORTED);
+ if (callback) { callback(NOT_SUPPORTED) }
+ reject(error);
+ }
- var cmd, lines, stats, speed;
+ _default_iface = _default_iface || getFirstExternalNetworkInterface();
+ iface = iface || _default_iface; // (_darwin ? 'en0' : 'eth0');
- if (_linux) {
- if (fs.existsSync('/sys/class/net/'+ iface)) {
- cmd =
- "cat /sys/class/net/" + iface + "/operstate; " +
- "cat /sys/class/net/" + iface + "/statistics/rx_bytes; " +
- "cat /sys/class/net/" + iface + "/statistics/tx_bytes; ";
- exec(cmd, function(error, stdout) {
- if (!error) {
- lines = stdout.toString().split('\n');
- result.operstate = lines[0].trim();
- result.rx = parseInt(lines[1]);
- result.tx = parseInt(lines[2]);
+ let result = {
+ iface: iface,
+ operstate: 'unknown',
+ rx: 0,
+ tx: 0,
+ rx_sec: -1,
+ tx_sec: -1,
+ ms: 0
+ };
- speed = calcNetworkSpeed(iface, result.rx, result.tx);
+ let cmd, lines, stats, speed;
- result.rx_sec = speed.rx_sec;
- result.tx_sec = speed.tx_sec;
- }
- callback(result);
- });
- } else callback(result);
- }
- if (_darwin) {
- cmd = "ifconfig " + iface + " | grep 'status'";
- exec(cmd, function(error, stdout) {
- result.operstate = (stdout.toString().split(':')[1] || '').trim();
- result.operstate = (result.operstate || '').toLowerCase();
- result.operstate = (result.operstate == 'active' ? 'up' : (result.operstate == 'inactive' ? 'down' : 'unknown'));
- cmd = "netstat -bI " + iface;
- exec(cmd, function(error, stdout) {
- if (!error) {
- lines = stdout.toString().split('\n');
- // if there is less than 2 lines, no information for this interface was found
- if (lines.length > 1 && lines[1].trim() != '') {
- // skip header line
- // use the second line because it is tied to the NIC instead of the ipv4 or ipv6 address
- stats = lines[1].replace(/ +/g, " ").split(' ');
- result.rx = parseInt(stats[6]);
- result.tx = parseInt(stats[9]);
+ if (_linux) {
+ if (fs.existsSync('/sys/class/net/' + iface)) {
+ cmd =
+ "cat /sys/class/net/" + iface + "/operstate; " +
+ "cat /sys/class/net/" + iface + "/statistics/rx_bytes; " +
+ "cat /sys/class/net/" + iface + "/statistics/tx_bytes; ";
+ exec(cmd, function (error, stdout) {
+ if (!error) {
+ lines = stdout.toString().split('\n');
+ result.operstate = lines[0].trim();
+ result.rx = parseInt(lines[1]);
+ result.tx = parseInt(lines[2]);
- speed = calcNetworkSpeed(iface, result.rx, result.tx);
+ speed = calcNetworkSpeed(iface, result.rx, result.tx);
- result.rx_sec = speed.rx_sec;
- result.tx_sec = speed.tx_sec;
- }
- }
- callback(result);
- });
- });
- }
+ result.rx_sec = speed.rx_sec;
+ result.tx_sec = speed.tx_sec;
+ result.ms = speed.ms;
+ }
+ if (callback) { callback(result) }
+ resolve(result);
+ });
+ } else {
+ if (callback) { callback(result) }
+ resolve(result);
+ }
+ }
+ if (_darwin) {
+ cmd = "ifconfig " + iface + " | grep 'status'";
+ exec(cmd, function (error, stdout) {
+ result.operstate = (stdout.toString().split(':')[1] || '').trim();
+ result.operstate = (result.operstate || '').toLowerCase();
+ result.operstate = (result.operstate == 'active' ? 'up' : (result.operstate == 'inactive' ? 'down' : 'unknown'));
+ cmd = "netstat -bI " + iface;
+ exec(cmd, function (error, stdout) {
+ if (!error) {
+ lines = stdout.toString().split('\n');
+ // if there is less than 2 lines, no information for this interface was found
+ if (lines.length > 1 && lines[1].trim() != '') {
+ // skip header line
+ // use the second line because it is tied to the NIC instead of the ipv4 or ipv6 address
+ stats = lines[1].replace(/ +/g, " ").split(' ');
+ result.rx = parseInt(stats[6]);
+ result.tx = parseInt(stats[9]);
+
+ speed = calcNetworkSpeed(iface, result.rx, result.tx);
+
+ result.rx_sec = speed.rx_sec;
+ result.tx_sec = speed.tx_sec;
+ }
+ }
+ if (callback) { callback(result) }
+ resolve(result);
+ });
+ });
+ }
+ });
+ });
}
exports.networkStats = networkStats;
@@ -883,28 +1192,155 @@ exports.networkStats = networkStats;
// NET - connections (sockets)
function networkConnections(callback) {
- if (_windows) {
- callback(NOT_SUPPORTED);
- }
- var cmd = 'netstat -tun | tail -n +3 | wc -l';
- var result;
- exec(cmd, function(error, stdout) {
- if (!error) {
- result = parseInt(stdout.toString());
- callback(result);
- } else {
- cmd = 'ss -tun | tail -n +2 | wc -l';
- exec(cmd, function(error, stdout) {
- if (!error) {
- result = parseInt(stdout.toString());
- } else {
- result = -1;
- }
- callback(result);
- })
- }
- })
+ return new Promise((resolve, reject) => {
+ process.nextTick(() => {
+ if (_windows) {
+ let error = new Error(NOT_SUPPORTED);
+ if (callback) { callback(NOT_SUPPORTED) }
+ reject(error);
+ }
+
+ var result = [];
+ if (_linux) {
+ let cmd = "netstat -tuna | grep 'ESTABLISHED\\|SYN_SENT\\|SYN_RECV\\|FIN_WAIT1\\|FIN_WAIT2\\|TIME_WAIT\\|CLOSE\\|CLOSE_WAIT\\|LAST_ACK\\|LISTEN\\|CLOSING\\|UNKNOWN\\|VERBUNDEN'";
+ exec(cmd, function (error, stdout) {
+ if (!error) {
+ var lines = stdout.toString().split('\n');
+ lines.forEach(function (line) {
+ line = line.replace(/ +/g, " ").split(' ');
+ if (line.length >= 6) {
+ let localip = line[3];
+ let localport = '';
+ let localaddress = line[3].split(':');
+ if (localaddress.length > 1) {
+ localport = localaddress[localaddress.length - 1];
+ localaddress.pop();
+ localip = localaddress.join(':');
+ }
+ let peerip = line[4];
+ let peerport = '';
+ let peeraddress = line[4].split(':');
+ if (peeraddress.length > 1) {
+ peerport = peeraddress[peeraddress.length - 1];
+ peeraddress.pop();
+ peerip = peeraddress.join(':');
+ }
+ let connstate = line[5];
+ if (connstate == 'VERBUNDEN') connstate = 'ESTABLISHED';
+ if (connstate) {
+ result.push({
+ protocol: line[0],
+ localaddress: localip,
+ localport: localport,
+ peeraddress: peerip,
+ peerport: peerport,
+ state: connstate
+ })
+ }
+ }
+ });
+ if (callback) {
+ callback(result)
+ }
+ resolve(result);
+ } else {
+ cmd = "ss -tuna | grep 'ESTAB\\|SYN-SENT\\|SYN-RECV\\|FIN-WAIT1\\|FIN-WAIT2\\|TIME-WAIT\\|CLOSE\\|CLOSE-WAIT\\|LAST-ACK\\|LISTEN\\|CLOSING'";
+ exec(cmd, function (error, stdout) {
+
+ if (!error) {
+ var lines = stdout.toString().split('\n');
+ lines.forEach(function (line) {
+ line = line.replace(/ +/g, " ").split(' ');
+ if (line.length >= 6) {
+ let localip = line[4];
+ let localport = '';
+ let localaddress = line[4].split(':');
+ if (localaddress.length > 1) {
+ localport = localaddress[localaddress.length - 1];
+ localaddress.pop();
+ localip = localaddress.join(':');
+ }
+ let peerip = line[5];
+ let peerport = '';
+ let peeraddress = line[5].split(':');
+ if (peeraddress.length > 1) {
+ peerport = peeraddress[peeraddress.length - 1];
+ peeraddress.pop();
+ peerip = peeraddress.join(':');
+ }
+ let connstate = line[1];
+ if (connstate == 'ESTAB') connstate = 'ESTABLISHED';
+ if (connstate == 'TIME-WAIT') connstate = 'TIME_WAIT';
+ if (connstate) {
+ result.push({
+ protocol: line[0],
+ localaddress: localip,
+ localport: localport,
+ peeraddress: peerip,
+ peerport: peerport,
+ state: connstate
+ })
+ }
+ }
+ });
+ }
+ if (callback) {
+ callback(result)
+ }
+ resolve(result);
+ })
+ }
+ })
+ }
+ if (_darwin) {
+ let cmd = "netstat -nat | grep 'ESTABLISHED\\|SYN_SENT\\|SYN_RECV\\|FIN_WAIT1\\|FIN_WAIT2\\|TIME_WAIT\\|CLOSE\\|CLOSE_WAIT\\|LAST_ACK\\|LISTEN\\|CLOSING\\|UNKNOWN'";
+ exec(cmd, function (error, stdout) {
+ if (!error) {
+
+ let lines = stdout.toString().split('\n');
+
+ lines.forEach(function (line) {
+ line = line.replace(/ +/g, " ").split(' ');
+ if (line.length >= 6) {
+ let localip = line[3];
+ let localport = '';
+ let localaddress = line[3].split('.');
+ if (localaddress.length > 1) {
+ localport = localaddress[localaddress.length - 1];
+ localaddress.pop();
+ localip = localaddress.join('.');
+ }
+ let peerip = line[4];
+ let peerport = '';
+ let peeraddress = line[4].split('.');
+ if (peeraddress.length > 1) {
+ peerport = peeraddress[peeraddress.length - 1];
+ peeraddress.pop();
+ peerip = peeraddress.join('.');
+ }
+ let connstate = line[5];
+ if (connstate) {
+ result.push({
+ protocol: line[0],
+ localaddress: localip,
+ localport: localport,
+ peeraddress: peerip,
+ peerport: peerport,
+ state: connstate
+ })
+ }
+ }
+ });
+ if (callback) {
+ callback(result)
+ }
+ resolve(result);
+ }
+ })
+ }
+ });
+ });
}
exports.networkConnections = networkConnections;
@@ -916,38 +1352,58 @@ exports.networkConnections = networkConnections;
// --------------------------
// PS - current load - in %
-function getLoad(callback) {
- var result = {};
- var loads = os.loadavg().map(function(x) { return x / _cores; } );
- result.avgload = parseFloat((Math.max.apply(Math, loads)).toFixed(2));
- result.currentload = -1;
+function getLoad() {
- var cmd = (_darwin) ? "ps -caxm -o pcpu" : "ps axo pcpu";
- exec(cmd, function(error, stdout) {
- if (!error) {
- var lines = stdout.toString().replace(/,+/g, ".").split('\n');
- lines.shift();
- lines.pop();
- result.currentload = parseFloat(((lines.reduce(function (pv, cv) {
- return pv + parseFloat(cv.trim());
- }, 0)) / _cores).toFixed(2));
- }
- callback(result)
- });
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ let result = {};
+ let loads = os.loadavg().map(function (x) { return x / _cores; });
+ result.avgload = parseFloat((Math.max.apply(Math, loads)).toFixed(2));
+ result.currentload = -1;
+
+ let cmd = (_darwin) ? "ps -caxm -o pcpu" : "ps axo pcpu";
+ exec(cmd, function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().replace(/,+/g, ".").split('\n');
+ lines.shift();
+ lines.pop();
+ result.currentload = parseFloat(((lines.reduce(function (pv, cv) {
+ return pv + parseFloat(cv.trim());
+ }, 0)) / _cores).toFixed(2));
+ }
+ resolve(result);
+ });
+ });
+ });
}
function currentLoad(callback) {
- if (_windows) {
- callback(NOT_SUPPORTED);
- }
- if (_cores == 0) {
- cores(function() {
- getLoad(callback)
- })
- } else {
- getLoad(callback)
- }
+ return new Promise((resolve, reject) => {
+ process.nextTick(() => {
+ if (_windows) {
+ let error = new Error(NOT_SUPPORTED);
+ if (callback) { callback(NOT_SUPPORTED) }
+ reject(error);
+ }
+
+ if (_cores == 0) {
+ cores()
+ .then(data => {
+ _cores = data;
+ getLoad().then(result => {
+ if (callback) { callback(result) }
+ resolve(result);
+ })
+ })
+ } else {
+ getLoad().then(result => {
+ if (callback) { callback(result) }
+ resolve(result);
+ })
+ }
+ });
+ });
}
exports.currentLoad = currentLoad;
@@ -956,94 +1412,126 @@ exports.currentLoad = currentLoad;
// PS - full load
// since bootup
-function getFullLoad(callback) {
- if (_windows) {
- callback(NOT_SUPPORTED);
- }
+function getFullLoad() {
- var result = {};
- if (_linux) {
- if (fs.existsSync('/proc/uptime')) {
- var output = fs.readFileSync('/proc/uptime').toString();
- output = output.replace(/ +/g, " ").split(' ');
- var uptime = parseFloat(output[0]);
- var idletime = parseFloat(output[1]) / _cores;
- result.fullload = (uptime - idletime) / uptime * 100.0;
- callback(result);
- }
- }
- if (_darwin) {
- result.fullload = 0;
- callback(result);
- }
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+
+ let result = {};
+ if (_linux) {
+ if (fs.existsSync('/proc/uptime')) {
+ let output = fs.readFileSync('/proc/uptime').toString();
+ output = output.replace(/ +/g, " ").split(' ');
+ let uptime = parseFloat(output[0]);
+ let idletime = parseFloat(output[1]) / _cores;
+ result.fullload = (uptime - idletime) / uptime * 100.0;
+ resolve(result);
+ }
+ }
+ if (_darwin) {
+ result.fullload = 0;
+ resolve(result);
+ }
+ });
+ });
}
function fullLoad(callback) {
- if (_cores == 0) {
- cores(function() {
- getFullLoad(callback)
- })
- } else {
- getFullLoad(callback)
- }
+
+ return new Promise((resolve, reject) => {
+ process.nextTick(() => {
+ if (_windows) {
+ let error = new Error(NOT_SUPPORTED);
+ if (callback) { callback(NOT_SUPPORTED) }
+ reject(error);
+ }
+
+ if (_cores == 0) {
+ cores()
+ .then(data => {
+ _cores = data;
+ getFullLoad().then(result => {
+ if (callback) { callback(result) }
+ resolve(result);
+ })
+ })
+ } else {
+ getFullLoad().then(result => {
+ if (callback) { callback(result) }
+ resolve(result);
+ })
+ }
+ });
+ });
}
exports.fullLoad = fullLoad;
-
// --------------------------
// PS - services
// pass a comma separated string with services to check (mysql, apache, postgresql, ...)
// this function gives an array back, if the services are running.
function services(srv, callback) {
- // fallback - if only callback is given
- if (isFunction(srv) && !callback) {
- callback = srv;
- srv = '';
- }
- if (_windows) {
- callback(NOT_SUPPORTED);
- }
+ // fallback - if only callback is given
+ if (isFunction(srv) && !callback) {
+ callback = srv;
+ srv = '';
+ }
- srv = srv.trim().replace(/,+/g, " ").replace(/ +/g, " ").replace(/ +/g, "|");
- var srvs = srv.split('|');
- var comm = (_darwin) ? "ps -caxm -o pcpu,pmem,comm" : "ps axo pcpu,pmem,comm";
- var data = [];
- if (srv != '' && srvs.length > 0) {
- exec(comm + " | grep -v grep | egrep '" + srv + "'", function (error, stdout) {
- if (!error) {
- var lines = stdout.toString().replace(/ +/g, " ").replace(/,+/g, ".").split('\n');
- srvs.forEach(function (srv) {
- var 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))
- })
- });
- callback(data)
- } else {
- srvs.forEach(function (srv) {
- data.push({
- 'name': srv,
- 'running': false,
- 'pcpu': 0,
- 'pmem': 0
- })
- });
- callback(data)
- }
- });
- } else callback(data)
+ 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, "|");
+ var srvs = srv.split('|');
+ var comm = (_darwin) ? "ps -caxm -o pcpu,pmem,comm" : "ps axo pcpu,pmem,comm";
+ var data = [];
+ if (srv != '' && srvs.length > 0) {
+ exec(comm + " | grep -v grep | egrep '" + srv + "'", function (error, stdout) {
+ if (!error) {
+ var lines = stdout.toString().replace(/ +/g, " ").replace(/,+/g, ".").split('\n');
+ srvs.forEach(function (srv) {
+ var 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);
+ }
+ });
+ });
}
exports.services = services;
@@ -1052,48 +1540,58 @@ exports.services = services;
// running processes
function processes(callback) {
- if (_windows) {
- callback(NOT_SUPPORTED);
- }
- exec("ps aux | grep -v 'ps aux' | wc -l", function(error, stdout) {
- var result = {
- all: 0,
- running: 0,
- blocked: 0
- };
- if (!error) {
- result.all = parseInt(stdout.toString());
- if (_darwin) {
- exec("ps axo state | grep 'R' | wc -l; ps axo state | grep 'U' | wc -l", function(error, stdout) {
- if (!error) {
- var lines = stdout.toString().split('\n');
- result.running = parseInt(lines[0]);
- result.blocked = parseInt(lines[1]);
- }
- callback(result);
- })
- }
- if (_linux) {
- exec("cat /proc/stat | grep procs_", function(error, stdout) {
- if (!error) {
- var lines = stdout.toString().split('\n');
- lines.forEach(function(line) {
- if (line.toUpperCase().indexOf('PROCS_RUNNING') != -1) {
- result.running = parseInt(line.replace(/ +/g, " ").split(' ')[1]);
- }
- if (line.toUpperCase().indexOf('PROCS_BLOCKED') != -1) {
- result.blocked = parseInt(line.replace(/ +/g, " ").split(' ')[1]);
- }
- })
- }
- callback(result);
- })
- }
- } else {
- callback(result);
- }
- });
+ return new Promise((resolve, reject) => {
+ process.nextTick(() => {
+ if (_windows) {
+ let error = new Error(NOT_SUPPORTED);
+ if (callback) { callback(NOT_SUPPORTED) }
+ reject(error);
+ }
+
+ var result = {
+ all: 0,
+ running: 0,
+ blocked: 0
+ };
+ exec("ps aux | grep -v 'ps aux' | wc -l", function (error, stdout) {
+ if (!error) {
+ result.all = parseInt(stdout.toString());
+ if (_darwin) {
+ exec("ps axo state | grep 'R' | wc -l; ps axo state | grep 'U' | wc -l", function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+ result.running = parseInt(lines[0]);
+ result.blocked = parseInt(lines[1]);
+ }
+ if (callback) { callback(result) }
+ resolve(result);
+ })
+ }
+ if (_linux) {
+ exec("cat /proc/stat | grep procs_", function (error, stdout) {
+ if (!error) {
+ let lines = stdout.toString().split('\n');
+ lines.forEach(function (line) {
+ if (line.toUpperCase().indexOf('PROCS_RUNNING') != -1) {
+ result.running = parseInt(line.replace(/ +/g, " ").split(' ')[1]);
+ }
+ if (line.toUpperCase().indexOf('PROCS_BLOCKED') != -1) {
+ result.blocked = parseInt(line.replace(/ +/g, " ").split(' ')[1]);
+ }
+ })
+ }
+ if (callback) { callback(result) }
+ resolve(result);
+ })
+ }
+ } else {
+ if (callback) { callback(result) }
+ resolve(result);
+ }
+ });
+ });
+ });
}
exports.processes = processes;
@@ -1104,45 +1602,55 @@ exports.processes = processes;
// (PID, CPU-Usage %, Mem-Usage %)
function processLoad(proc, callback) {
- // fallback - if only callback is given
- if (isFunction(proc) && !callback) {
- callback = proc;
- proc = '';
- }
- if (_windows) {
- callback(NOT_SUPPORTED);
- }
+ // fallback - if only callback is given
+ if (isFunction(proc) && !callback) {
+ callback = proc;
+ proc = '';
+ }
- var result = {
- 'proc' : proc,
- 'pid' : -1,
- 'cpu' : 0,
- 'mem' : 0
- };
+ return new Promise((resolve, reject) => {
+ process.nextTick(() => {
+ if (_windows) {
+ let error = new Error(NOT_SUPPORTED);
+ if (callback) { callback(NOT_SUPPORTED) }
+ reject(error);
+ }
- if (proc) {
- exec("ps aux | grep " + proc + " | grep -v grep", function(error, stdout) {
- if (!error) {
- var data = stdout.replace(/ +/g, " ").split(' ');
+ var result = {
+ 'proc': proc,
+ 'pid': -1,
+ 'cpu': 0,
+ 'mem': 0
+ };
- if (data.length > 2) {
- result = {
- 'proc' : proc,
- 'pid' : data[1],
- 'cpu' : parseFloat(data[2].replace(',', '.')),
- 'mem' : parseFloat(data[3].replace(',', '.'))
- }
- }
- }
- callback(result);
- });
- } else callback(result);
+ if (proc) {
+ exec("ps aux | grep " + proc + " | grep -v grep", function (error, stdout) {
+ if (!error) {
+ let data = stdout.replace(/ +/g, " ").split(' ');
+
+ if (data.length > 2) {
+ result = {
+ 'proc': proc,
+ 'pid': data[1],
+ 'cpu': parseFloat(data[2].replace(',', '.')),
+ 'mem': parseFloat(data[3].replace(',', '.'))
+ }
+ }
+ }
+ if (callback) { callback(result) }
+ resolve(result);
+ });
+ } else {
+ if (callback) { callback(result) }
+ resolve(result);
+ }
+ });
+ });
}
exports.processLoad = processLoad;
-
// ----------------------------------------------------------------------------------
// 9. Users/Sessions
// ----------------------------------------------------------------------------------
@@ -1151,17 +1659,147 @@ exports.processLoad = processLoad;
// array of users online = sessions
function users(callback) {
- if (_windows) {
- callback(NOT_SUPPORTED);
- }
- var result = [];
- exec("users", function(error, stdout) {
- if (!error) {
- result = stdout.toString().replace(/ +/g, " ").replace(/\n+/g, " ").trim().split(' ').filter(function(e) {return e.trim() !== ''});
- }
- callback(result);
- });
+ return new Promise((resolve, reject) => {
+ process.nextTick(() => {
+ if (_windows) {
+ let error = new Error(NOT_SUPPORTED);
+ if (callback) { callback(NOT_SUPPORTED) }
+ reject(error);
+ }
+
+ var result = [];
+ var result_who = [];
+ var result_w = {};
+ var w_first = true;
+ var w_header = [];
+ var w_pos = [];
+ var w_headerline = '';
+ var who_line = {};
+
+ // linux
+ if (_linux) {
+ exec("who --ips; echo '---'; w | tail -n +2", function (error, stdout) {
+ if (!error) {
+ // lines / split
+ var lines = stdout.toString().split('\n');
+ var is_whopart = true;
+ lines.forEach(function (line) {
+ if (line == '---') {
+ is_whopart = false;
+ } else {
+ var l = line.replace(/ +/g, " ").split(' ');
+
+ // who part
+ if (is_whopart) {
+ result_who.push({
+ user: l[0],
+ tty: l[1],
+ date: l[2],
+ time: l[3],
+ ip: (l && l.length > 4) ? l[4] : ''
+ })
+ } else {
+ // w part
+ if (w_first) { // header
+ w_header = l;
+ w_headerline = line;
+ w_header.forEach(function(item) {
+ w_pos.push(line.indexOf(item))
+ });
+ w_first = false;
+ // console.log(w_pos);
+ // console.log(result_who);
+ } else {
+ // split by w_pos
+ result_w.user = line.substring(w_pos[0], w_pos[1]-1).trim();
+ result_w.tty = line.substring(w_pos[1], w_pos[2]-1).trim();
+ result_w.ip = line.substring(w_pos[2], w_pos[3]-1).trim();
+ result_w.command = line.substring(w_pos[7], 1000).trim();
+ // console.log(result_w);
+ // find corresponding 'who' line
+ who_line = result_who.filter(function(obj) {
+ return (obj.user.substring(0,8).trim() == result_w.user && obj.tty == result_w.tty)
+ });
+ if (who_line.length == 1) {
+ result.push({
+ user: who_line[0].user,
+ tty: who_line[0].tty,
+ date: who_line[0].date,
+ time: who_line[0].time,
+ ip: who_line[0].ip,
+ command: result_w.command
+ })
+ }
+ }
+ }
+ }
+ });
+ if (callback) { callback(result) }
+ resolve(result);
+ } else {
+ if (callback) { callback(result) }
+ resolve(result);
+ }
+ });
+ }
+
+ if (_darwin) {
+ exec("who; echo '---'; w -ih", function (error, stdout) {
+ if (!error) {
+ // lines / split
+ var lines = stdout.toString().split('\n');
+ var is_whopart = true;
+ lines.forEach(function (line) {
+ if (line == '---') {
+ is_whopart = false;
+ } else {
+ var l = line.replace(/ +/g, " ").split(' ');
+
+ // who part
+ if (is_whopart) {
+ result_who.push({
+ user: l[0],
+ tty: l[1],
+ date: ("" + new Date().getFullYear()) + '-' + ("0" + ("JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC".indexOf(l[2].toUpperCase()) / 3 + 1)).slice(-2) + '-' + ("0" + l[3]).slice(-2),
+ time: l[4],
+ })
+ } else {
+ // w part
+ // split by w_pos
+ result_w.user = l[0];
+ result_w.tty = l[1];
+ result_w.ip = (l[2] != '-') ? l[2] : '';
+ result_w.command = l.slice(5, 1000).join(' ');
+ // find corresponding 'who' line
+ who_line = result_who.filter(function(obj) {
+ return (obj.user == result_w.user && (obj.tty.substring(3,1000) == result_w.tty || obj.tty == result_w.tty))
+ });
+ if (who_line.length == 1) {
+ result.push({
+ user: who_line[0].user,
+ tty: who_line[0].tty,
+ date: who_line[0].date,
+ time: who_line[0].time,
+ ip: result_w.ip,
+ command: result_w.command
+ })
+ }
+ }
+ }
+ });
+ if (callback) { callback(result) }
+ resolve(result);
+ } else {
+ if (callback) { callback(result) }
+ resolve(result);
+ }
+ });
+ }
+
+
+ });
+ });
}
exports.users = users;
@@ -1175,30 +1813,38 @@ exports.users = users;
function inetChecksite(url, callback) {
- if (_windows) {
- callback(NOT_SUPPORTED);
- }
+ return new Promise((resolve, reject) => {
+ process.nextTick(() => {
+ if (_windows) {
+ let error = new Error(NOT_SUPPORTED);
+ if (callback) { callback(NOT_SUPPORTED) }
+ reject(error);
+ }
- var result = {
- url: url,
- ok : false,
- status: 404,
- ms : -1
- };
- if (url && (isFunction(callback))) {
- var t = Date.now();
- var args = " -I --connect-timeout 5 -m 5 " + url + " 2>/dev/null | head -n 1 | cut -d ' ' -f2";
- var cmd = "curl";
- exec(cmd + args, function(error, stdout) {
- var statusCode = parseInt(stdout.toString());
- result.status = statusCode || 404;
- result.ok = !error && (statusCode == 200 || statusCode == 301 || statusCode == 302 || statusCode == 304);
- result.ms = (result.ok ? Date.now() - t : -1);
- callback(result);
- })
- } else {
- callback(result)
- }
+ var result = {
+ url: url,
+ ok: false,
+ status: 404,
+ ms: -1
+ };
+ if (url) {
+ var t = Date.now();
+ let args = " -I --connect-timeout 5 -m 5 " + url + " 2>/dev/null | head -n 1 | cut -d ' ' -f2";
+ let cmd = "curl";
+ exec(cmd + args, function (error, stdout) {
+ let statusCode = parseInt(stdout.toString());
+ result.status = statusCode || 404;
+ result.ok = !error && (statusCode == 200 || statusCode == 301 || statusCode == 302 || statusCode == 304);
+ result.ms = (result.ok ? Date.now() - t : -1);
+ if (callback) { callback(result) }
+ resolve(result);
+ })
+ } else {
+ if (callback) { callback(result) }
+ resolve(result);
+ }
+ });
+ });
}
exports.inetChecksite = inetChecksite;
@@ -1206,27 +1852,43 @@ exports.inetChecksite = inetChecksite;
// --------------------------
// check inet latency
-function inetLatency(callback) {
- if (_windows) {
- callback(NOT_SUPPORTED);
- }
+function inetLatency(host, callback) {
- var t = Date.now();
- var cmd;
- if (_linux) {
- cmd = "ping -c 2 -w 3 8.8.8.8 | grep rtt | cut -d'/' -f4 | awk '{ print $3 }'";
- }
- if (_darwin) {
- cmd = "ping -c 2 -t 3 8.8.8.8 | grep avg | cut -d'/' -f4 | awk '{ print $3 }'";
- }
+ // fallback - if only callback is given
+ if (isFunction(host) && !callback) {
+ callback = host;
+ host = '';
+ }
- exec(cmd, function(error, stdout) {
- if (!error) {
- callback(parseFloat(stdout.toString()));
- } else {
- callback(-1)
- }
- })
+ host = host || '8.8.8.8';
+
+ return new Promise((resolve, reject) => {
+ process.nextTick(() => {
+ if (_windows) {
+ let error = new Error(NOT_SUPPORTED);
+ if (callback) { callback(NOT_SUPPORTED) }
+ reject(error);
+ }
+
+ var t = Date.now();
+ let cmd;
+ if (_linux) {
+ cmd = "ping -c 2 -w 3 " + host + " | grep rtt | cut -d'/' -f4 | awk '{ print $3 }'";
+ }
+ if (_darwin) {
+ cmd = "ping -c 2 -t 3 " + host + " | grep avg | cut -d'/' -f4 | awk '{ print $3 }'";
+ }
+
+ exec(cmd, function (error, stdout) {
+ let result = -1;
+ if (!error) {
+ result = parseFloat(stdout.toString());
+ }
+ if (callback) { callback(result) }
+ resolve(result);
+ })
+ });
+ });
}
exports.inetLatency = inetLatency;
@@ -1238,29 +1900,36 @@ exports.inetLatency = inetLatency;
// --------------------------
// get static data - they should not change until restarted
-
function getStaticData(callback) {
- if (_windows) {
- callback(NOT_SUPPORTED);
- }
- var data = {};
+ return new Promise((resolve, reject) => {
+ process.nextTick(() => {
+ if (_windows) {
+ let error = new Error(NOT_SUPPORTED);
+ if (callback) { callback(NOT_SUPPORTED) }
+ reject(error);
+ }
- data.version = version();
+ var data = {};
- system(function(res) {
- data.system = res;
- osInfo(function(res) {
- data.os = res;
- cpu(function(res) {
- data.cpu = res;
- networkInterfaces(function(res) {
- data.net = res;
- callback(data);
- })
- })
- })
- })
+ data.version = version();
+
+ system().then(res => {
+ data.system = res;
+ osInfo().then(res => {
+ data.os = res;
+ cpu().then(res => {
+ data.cpu = res;
+ networkInterfaces().then(res => {
+ data.net = res;
+ if (callback) { callback(data) }
+ resolve(data);
+ })
+ })
+ })
+ })
+ });
+ });
}
exports.getStaticData = getStaticData;
@@ -1271,61 +1940,123 @@ exports.getStaticData = getStaticData;
// --------------------------
// 2 additional parameters needed
// - srv: comma separated list of services to monitor e.g. "mysql, apache, postgresql"
-// - network: define network for which you like to monitor network speed e.g. "eth0"
+// - iface: define network interface for which you like to monitor network speed e.g. "eth0"
-function getDynamicData(callback, srv, network) {
+function getDynamicData(srv, iface, callback) {
- if (_windows) {
- callback(NOT_SUPPORTED);
- }
+ if (isFunction(iface)) {
+ callback = iface;
+ iface = '';
+ }
+ if (isFunction(srv)) {
+ callback = srv;
+ srv = '';
+ }
- network = network || (_darwin ? 'en0' : 'eth0');
- srv = srv || '';
+ return new Promise((resolve, reject) => {
+ process.nextTick(() => {
+ if (_windows) {
+ let error = new Error(NOT_SUPPORTED);
+ if (callback) { callback(NOT_SUPPORTED) }
+ reject(error);
+ }
- var data = {};
+ iface = iface || getFirstExternalNetworkInterface();
+ srv = srv || '';
- // get time
- data.time = time();
- data.node = process.versions.node;
- data.v8 = process.versions.v8;
+ // use closure to track ƒ completion
+ var functionProcessed = (function () {
+ var totalFunctions = 13;
- cpuCurrentspeed(function(res) {
- data.cpuCurrentspeed = res;
- users(function(res) {
- data.users = res;
- processes(function(res) {
- data.processes = res;
- currentLoad(function(res) {
- data.currentLoad = res;
- cpuTemperature(function(res) {
- data.temp = res;
- networkStats(network, function(res) {
- data.networkStats = res;
- networkConnections(function(res) {
- data.networkConnections = res;
- mem(function(res) {
- data.mem = res;
- services(srv, function(res) {
- data.services = res;
- fsSize(function(res) {
- data.fsSize = res;
- fsStats(function(res) {
- data.fsStats=res;
- inetLatency(function(res) {
- data.inetLatency = res;
- callback(data);
- });
- });
- });
- });
- });
- });
- });
- });
- });
- });
- });
- });
+ return function () {
+ if (--totalFunctions === 0) {
+ if (callback) { callback(data) }
+ resolve(data);
+ }
+ };
+ })();
+
+ // var totalFunctions = 12;
+ // function functionProcessed() {
+ // if (--totalFunctions === 0) {
+ // if (callback) { callback(data) }
+ // resolve(data);
+ // }
+ // }
+
+ var data = {};
+
+ // get time
+ data.time = time();
+ data.node = process.versions.node;
+ data.v8 = process.versions.v8;
+
+ cpuCurrentspeed().then(res => {
+ data.cpuCurrentspeed = res;
+ functionProcessed();
+ });
+
+ users().then(res => {
+ data.users = res;
+ functionProcessed();
+ });
+
+ processes().then(res => {
+ data.processes = res;
+ functionProcessed();
+ });
+
+ currentLoad().then(res => {
+ data.currentLoad = res;
+ functionProcessed();
+ });
+
+ cpuTemperature().then(res => {
+ data.temp = res;
+ functionProcessed();
+ });
+
+ networkStats(iface).then(res => {
+ data.networkStats = res;
+ functionProcessed();
+ });
+
+ networkConnections().then(res => {
+ data.networkConnections = res;
+ functionProcessed();
+ });
+
+ mem().then(res => {
+ data.mem = res;
+ functionProcessed();
+ });
+
+ services(srv).then(res => {
+ data.services = res;
+ functionProcessed();
+ });
+
+ fsSize().then(res => {
+ data.fsSize = res;
+ functionProcessed();
+ });
+
+ fsStats().then(res => {
+ data.fsStats = res;
+ functionProcessed();
+ });
+
+ disksIO().then(res => {
+ data.disksIO = res;
+ functionProcessed();
+ });
+
+ inetLatency().then(res => {
+ data.inetLatency = res;
+ functionProcessed();
+ });
+ });
+ });
}
exports.getDynamicData = getDynamicData;
@@ -1335,26 +2066,34 @@ exports.getDynamicData = getDynamicData;
// --------------------------
// 2 additional parameters needed
// - srv: comma separated list of services to monitor e.g. "mysql, apache, postgresql"
-// - network: define network for which you like to monitor network speed e.g. "eth0"
+// - iface: define network interface for which you like to monitor network speed e.g. "eth0"
-function getAllData(callback, srv, network) {
- if (_windows) {
- callback(NOT_SUPPORTED);
- }
+function getAllData(srv, iface, callback) {
- var data = {};
+ return new Promise((resolve, reject) => {
+ process.nextTick(() => {
+ if (_windows) {
+ let error = new Error(NOT_SUPPORTED);
+ if (callback) { callback(NOT_SUPPORTED) }
+ reject(error);
+ }
- getStaticData(function(res) {
- data = res;
- getDynamicData(function(res) {
- for(var key in res) {
- if (res.hasOwnProperty(key)) {
- data[key]=res[key];
- }
- }
- callback(data);
- }, srv, network);
- })
+ var data = {};
+
+ getStaticData().then(res => {
+ data = res;
+ getDynamicData(srv, iface).then(res => {
+ for (var key in res) {
+ if (res.hasOwnProperty(key)) {
+ data[key] = res[key];
+ }
+ }
+ if (callback) { callback(data) }
+ resolve(data);
+ });
+ })
+ });
+ });
}
exports.getAllData = getAllData;
diff --git a/package.json b/package.json
index 40202fa..dd53464 100644
--- a/package.json
+++ b/package.json
@@ -34,6 +34,6 @@
"linux"
],
"engines": {
- "node": ">=0.10"
+ "node": ">=4.0.0"
}
}