added versions (kernel, ssl, node, npm, pm2, ...)

This commit is contained in:
Sebastian Hildebrandt 2016-09-16 13:12:04 +02:00
parent e1827fd78b
commit d338e90e83
2 changed files with 122 additions and 76 deletions

View File

@ -42,6 +42,7 @@ si.cpu()
### Latest Activity ### Latest Activity
- Version 3.6.0: added versions (kernel, ssl, node, npm, pm2, ...).
- Version 3.5.0: added graphics info (controller and display). - Version 3.5.0: added graphics info (controller and display).
- Version 3.4.0: rewritten currentLoad and CPU load for processes (linux). This is now much more accurate. - Version 3.4.0: rewritten currentLoad and CPU load for processes (linux). This is now much more accurate.
- Version 3.3.0: added process list. Get full process list including details like cpu and mem usage, status, command, ... - Version 3.3.0: added process list. Get full process list including details like cpu and mem usage, status, command, ...
@ -69,6 +70,7 @@ Here all changes more detailed:
New Functions New Functions
- `versions`: returns object of versions - kernel, ssl, node, npm, ...(new in version 3.6)
- `graphics`: returns arrays of graphics controllers and displays (new in version 3.5) - `graphics`: returns arrays of graphics controllers and displays (new in version 3.5)
- `networkInterfaceDefault`: returns default network interface (new in version 3.4) - `networkInterfaceDefault`: returns default network interface (new in version 3.4)
- `processes`: now returns also a process list with all process details (new in version 3.3) - `processes`: now returns also a process list with all process details (new in version 3.3)
@ -188,6 +190,7 @@ This library is splitted in several sections:
| - arch | X | X | same as os.arch() | | - arch | X | X | same as os.arch() |
| - hostname | X | X | same as os.hostname() | | - hostname | X | X | same as os.hostname() |
| - logofile | X | X | e.g. 'apple', 'debian', 'fedora', ... | | - logofile | X | X | e.g. 'apple', 'debian', 'fedora', ... |
| si.versions(cb) | X | X | Version information (kernel, ssl, node, ...) |
| si.cpu(cb) | X | X | CPU information| | si.cpu(cb) | X | X | CPU information|
| - manufacturer | X | X | e.g. 'Intel(R)' | | - manufacturer | X | X | e.g. 'Intel(R)' |
| - brand | X | X | e.g. 'Core(TM)2 Duo' | | - brand | X | X | e.g. 'Core(TM)2 Duo' |
@ -394,6 +397,7 @@ I am happy to discuss any comments and suggestions. Please feel free to contact
| Version | Date | Comment | | Version | Date | Comment |
| -------------- | -------------- | -------- | | -------------- | -------------- | -------- |
| 3.6.0 | 2016-09-14 | added versions (kernel, ssl, node, npm, pm2, ...) |
| 3.5.1 | 2016-09-14 | bugfix graphics info | | 3.5.1 | 2016-09-14 | bugfix graphics info |
| 3.5.0 | 2016-09-14 | added graphics info (controller, display) | | 3.5.0 | 2016-09-14 | added graphics info (controller, display) |
| 3.4.4 | 2016-09-02 | tiny fixes system.model, getDefaultNetworkInterface | | 3.4.4 | 2016-09-02 | tiny fixes system.model, getDefaultNetworkInterface |

View File

@ -81,6 +81,7 @@
// -------------------------------- // --------------------------------
// //
// version date comment // version date comment
// 3.6.0 2016-09-16 added versions (kernel, ssl, node, npm, pm2, ...)
// 3.5.1 2016-09-14 bugfix graphics info // 3.5.1 2016-09-14 bugfix graphics info
// 3.5.0 2016-09-14 added graphics info (controller, display) // 3.5.0 2016-09-14 added graphics info (controller, display)
// 3.4.4 2016-09-02 tiny fixes system.model, getDefaultNetworkInterface // 3.4.4 2016-09-02 tiny fixes system.model, getDefaultNetworkInterface
@ -435,6 +436,45 @@ function osInfo(callback) {
exports.osInfo = osInfo; exports.osInfo = osInfo;
function versions(callback) {
return new Promise((resolve, reject) => {
process.nextTick(() => {
if (_windows) {
let error = new Error(NOT_SUPPORTED);
if (callback) { callback(NOT_SUPPORTED) }
reject(error);
}
let result = {
kernel: os.release(),
node: process.versions.node,
v8: process.versions.v8,
npm: '',
pm2: '',
openssl: process.versions.openssl
};
let lines = [];
exec("npm -v", function (error, stdout) {
if (!error) {
result.npm = stdout.toString().split('\n')[0];
}
exec("pm2 -v", function (error, stdout) {
if (!error) {
lines = stdout.toString().split('\n');
if (lines.length >= 2) {
result.pm2 = lines[lines.length-2];
}
}
if (callback) { callback(result) }
resolve(result);
});
});
});
});
}
exports.versions = versions;
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// 4. CPU // 4. CPU
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
@ -816,7 +856,6 @@ function mem(callback) {
exports.mem = mem; exports.mem = mem;
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// 6. Battery // 6. Battery
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
@ -1013,8 +1052,7 @@ function graphics(callback) {
is_vga = true; is_vga = true;
let endpos = lines[i].search(/\[[0-9a-f]{4}:[0-9a-f]{4}]|$/); let endpos = lines[i].search(/\[[0-9a-f]{4}:[0-9a-f]{4}]|$/);
let parts = lines[i].substr(vgapos, endpos - vgapos).split(':'); let parts = lines[i].substr(vgapos, endpos - vgapos).split(':');
if (parts.length > 1) if (parts.length > 1) {
{
parts[1] = parts[1].trim(); parts[1] = parts[1].trim();
if (parts[1].toLowerCase().indexOf('corporation')) { if (parts[1].toLowerCase().indexOf('corporation')) {
currentController.vendor = parts[1].substr(0, parts[1].toLowerCase().indexOf('corporation') + 11).trim(); currentController.vendor = parts[1].substr(0, parts[1].toLowerCase().indexOf('corporation') + 11).trim();
@ -1059,30 +1097,30 @@ function graphics(callback) {
let result = {}; let result = {};
// find first "Detailed Timing Description" // find first "Detailed Timing Description"
let start = 108; let start = 108;
if (edid.substr(start,6) == '000000') { if (edid.substr(start, 6) == '000000') {
start += 36; start += 36;
} }
if (edid.substr(start,6) == '000000') { if (edid.substr(start, 6) == '000000') {
start += 36; start += 36;
} }
if (edid.substr(start,6) == '000000') { if (edid.substr(start, 6) == '000000') {
start += 36; start += 36;
} }
if (edid.substr(start,6) == '000000') { if (edid.substr(start, 6) == '000000') {
start += 36; start += 36;
} }
result.resolutionx = parseInt('0x0' + edid.substr(start + 8,1) + edid.substr(start + 4,2)); result.resolutionx = parseInt('0x0' + edid.substr(start + 8, 1) + edid.substr(start + 4, 2));
result.resolutiony = parseInt('0x0' + edid.substr(start + 14,1) + edid.substr(start + 10,2)); result.resolutiony = parseInt('0x0' + edid.substr(start + 14, 1) + edid.substr(start + 10, 2));
result.sizex = parseInt('0x0' + edid.substr(start + 28,1) + edid.substr(start + 24,2)); result.sizex = parseInt('0x0' + edid.substr(start + 28, 1) + edid.substr(start + 24, 2));
result.sizey = parseInt('0x0' + edid.substr(start + 29,1) + edid.substr(start + 26,2)); result.sizey = parseInt('0x0' + edid.substr(start + 29, 1) + edid.substr(start + 26, 2));
// monitor name // monitor name
start = edid.indexOf('000000fc00'); // find first "Monitor Description Data" start = edid.indexOf('000000fc00'); // find first "Monitor Description Data"
if (start >= 0) { if (start >= 0) {
let model_raw = edid.substr(start+10, 26); let model_raw = edid.substr(start + 10, 26);
if (model_raw.indexOf('0a') != -1) { if (model_raw.indexOf('0a') != -1) {
model_raw = model_raw.substr(0,model_raw.indexOf('0a')) model_raw = model_raw.substr(0, model_raw.indexOf('0a'))
} }
result.model = model_raw.match(/.{1,2}/g).map(function(v){ result.model = model_raw.match(/.{1,2}/g).map(function (v) {
return String.fromCharCode(parseInt(v, 16)); return String.fromCharCode(parseInt(v, 16));
}).join(''); }).join('');
} else { } else {
@ -1099,7 +1137,7 @@ function graphics(callback) {
let start = 0; let start = 0;
for (let i = 1; i < lines.length; i++) { // start with second line for (let i = 1; i < lines.length; i++) { // start with second line
if ('' != lines[i].trim()) { if ('' != lines[i].trim()) {
if (' ' != lines[i][0] && '\t' != lines[i][0] && lines[i].toLowerCase().indexOf(' connected ') != -1 ) { // first line of new entry if (' ' != lines[i][0] && '\t' != lines[i][0] && lines[i].toLowerCase().indexOf(' connected ') != -1) { // first line of new entry
if (Object.keys(currentDisplay).length > 0) { // push last display to array if (Object.keys(currentDisplay).length > 0) { // push last display to array
displays.push(currentDisplay); displays.push(currentDisplay);
currentDisplay = {}; currentDisplay = {};
@ -1126,7 +1164,7 @@ function graphics(callback) {
is_edid = false; is_edid = false;
} }
} }
if (lines[i].toLowerCase().indexOf('edid:') != -1 ) { if (lines[i].toLowerCase().indexOf('edid:') != -1) {
is_edid = true; is_edid = true;
start = lines[i].search(/\S|$/); start = lines[i].search(/\S|$/);
} }
@ -2072,8 +2110,8 @@ function processes(callback) {
to = i - 1; to = i - 1;
result.push({ result.push({
from: from, from: from,
to: to+1, to: to + 1,
cap: head.substring(from, to+1) cap: head.substring(from, to + 1)
}); });
from = to + 2; from = to + 2;
count++; count++;
@ -2106,19 +2144,19 @@ function processes(callback) {
} }
function parseLine(line) { function parseLine(line) {
let pid = parseInt(line.substring(parsedhead[0].from,parsedhead[0].to)); let pid = parseInt(line.substring(parsedhead[0].from, parsedhead[0].to));
let pcpu = parseFloat(line.substring(parsedhead[1].from,parsedhead[1].to).replace(/,/g, ".")); let pcpu = parseFloat(line.substring(parsedhead[1].from, parsedhead[1].to).replace(/,/g, "."));
let pmem = parseFloat(line.substring(parsedhead[2].from,parsedhead[2].to).replace(/,/g, ".")); let pmem = parseFloat(line.substring(parsedhead[2].from, parsedhead[2].to).replace(/,/g, "."));
let priority = parseInt(line.substring(parsedhead[3].from,parsedhead[3].to)); let priority = parseInt(line.substring(parsedhead[3].from, parsedhead[3].to));
let vsz = parseInt(line.substring(parsedhead[4].from,parsedhead[4].to)); let vsz = parseInt(line.substring(parsedhead[4].from, parsedhead[4].to));
let rss = parseInt(line.substring(parsedhead[5].from,parsedhead[5].to)); let rss = parseInt(line.substring(parsedhead[5].from, parsedhead[5].to));
let started = line.substring(parsedhead[6].from,parsedhead[6].to).trim(); let started = line.substring(parsedhead[6].from, parsedhead[6].to).trim();
let state = line.substring(parsedhead[7].from,parsedhead[7].to).trim(); let state = line.substring(parsedhead[7].from, parsedhead[7].to).trim();
state = (state[0] == 'R' ? 'running': (state[0] == 'S' ? 'sleeping': (state[0] == 'T' ? 'stopped': (state[0] == 'W' ? 'paging': (state[0] == 'X' ? 'dead': (state[0] == 'Z' ? 'zombie': ((state[0] == 'D' || state[0] == 'U') ? 'blocked': 'unknown'))))))); state = (state[0] == 'R' ? 'running' : (state[0] == 'S' ? 'sleeping' : (state[0] == 'T' ? 'stopped' : (state[0] == 'W' ? 'paging' : (state[0] == 'X' ? 'dead' : (state[0] == 'Z' ? 'zombie' : ((state[0] == 'D' || state[0] == 'U') ? 'blocked' : 'unknown')))))));
let tty = line.substring(parsedhead[8].from,parsedhead[8].to).trim(); let tty = line.substring(parsedhead[8].from, parsedhead[8].to).trim();
if (tty == '?' || tty == '??') tty = ''; if (tty == '?' || tty == '??') tty = '';
let user = line.substring(parsedhead[9].from,parsedhead[9].to).trim(); let user = line.substring(parsedhead[9].from, parsedhead[9].to).trim();
let command = line.substring(parsedhead[10].from,parsedhead[10].to).trim().replace(/\[/g, "").replace(/]/g, ""); let command = line.substring(parsedhead[10].from, parsedhead[10].to).trim().replace(/\[/g, "").replace(/]/g, "");
return ({ return ({
pid: pid, pid: pid,
@ -2164,6 +2202,7 @@ function processes(callback) {
let guest_nice = (parts.length >= 11 ? parseInt(parts[10]) : 0); let guest_nice = (parts.length >= 11 ? parseInt(parts[10]) : 0);
return user + nice + system + idle + iowait + irq + softirq + steal + guest + guest_nice; return user + nice + system + idle + iowait + irq + softirq + steal + guest + guest_nice;
} }
function parseProcPidStat(line, all) { function parseProcPidStat(line, all) {
let parts = line.replace(/ +/g, " ").split(' '); let parts = line.replace(/ +/g, " ").split(' ');
if (parts.length >= 17) { if (parts.length >= 17) {
@ -2240,7 +2279,7 @@ function processes(callback) {
if (_linux) { if (_linux) {
// calc process_cpu - ps is not accurate in linux! // calc process_cpu - ps is not accurate in linux!
cmd = "cat /proc/stat | grep 'cpu '"; cmd = "cat /proc/stat | grep 'cpu '";
for (let i=0; i< result.list.length; i++) { for (let i = 0; i < result.list.length; i++) {
cmd += (';cat /proc/' + result.list[i].pid + '/stat') cmd += (';cat /proc/' + result.list[i].pid + '/stat')
} }
exec(cmd, function (error, stdout) { exec(cmd, function (error, stdout) {
@ -2252,13 +2291,13 @@ function processes(callback) {
// process // process
let list_new = {}; let list_new = {};
let resultProcess = {}; let resultProcess = {};
for (let i=0; i< curr_processes.length; i++) { for (let i = 0; i < curr_processes.length; i++) {
resultProcess = parseProcPidStat(curr_processes[i], all); resultProcess = parseProcPidStat(curr_processes[i], all);
if (resultProcess.pid) { if (resultProcess.pid) {
// store pcpu in outer array // store pcpu in outer array
let listPos = result.list.map(function(e) { return e.pid; }).indexOf(resultProcess.pid); let listPos = result.list.map(function (e) { return e.pid; }).indexOf(resultProcess.pid);
if (listPos >= 0) { if (listPos >= 0) {
result.list[listPos].pcpu = resultProcess.pcpuu + resultProcess.pcpus result.list[listPos].pcpu = resultProcess.pcpuu + resultProcess.pcpus
} }
@ -2387,19 +2426,19 @@ function parseUsers1(lines) {
if (w_first) { // header if (w_first) { // header
w_header = l; w_header = l;
w_headerline = line; w_headerline = line;
w_header.forEach(function(item) { w_header.forEach(function (item) {
w_pos.push(line.indexOf(item)) w_pos.push(line.indexOf(item))
}); });
w_first = false; w_first = false;
} else { } else {
// split by w_pos // split by w_pos
result_w.user = line.substring(w_pos[0], w_pos[1]-1).trim(); 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.tty = line.substring(w_pos[1], w_pos[2] - 1).trim();
result_w.ip = line.substring(w_pos[2], w_pos[3]-1).replace(/\(/g, "").replace(/\)/g, "").trim(); result_w.ip = line.substring(w_pos[2], w_pos[3] - 1).replace(/\(/g, "").replace(/\)/g, "").trim();
result_w.command = line.substring(w_pos[7], 1000).trim(); result_w.command = line.substring(w_pos[7], 1000).trim();
// find corresponding 'who' line // find corresponding 'who' line
who_line = result_who.filter(function(obj) { who_line = result_who.filter(function (obj) {
return (obj.user.substring(0,8).trim() == result_w.user && obj.tty == result_w.tty) return (obj.user.substring(0, 8).trim() == result_w.user && obj.tty == result_w.tty)
}); });
if (who_line.length == 1) { if (who_line.length == 1) {
result.push({ result.push({
@ -2447,8 +2486,8 @@ function parseUsers2(lines) {
result_w.ip = (l[2] != '-') ? l[2] : ''; result_w.ip = (l[2] != '-') ? l[2] : '';
result_w.command = l.slice(5, 1000).join(' '); result_w.command = l.slice(5, 1000).join(' ');
// find corresponding 'who' line // find corresponding 'who' line
who_line = result_who.filter(function(obj) { 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)) return (obj.user == result_w.user && (obj.tty.substring(3, 1000) == result_w.tty || obj.tty == result_w.tty))
}); });
if (who_line.length == 1) { if (who_line.length == 1) {
result.push({ result.push({
@ -2525,7 +2564,6 @@ function users(callback) {
}); });
} }
}); });
}); });
} }
@ -2640,6 +2678,7 @@ function dockerContainers(all, callback) {
}); });
return (filtered.length > 0); return (filtered.length > 0);
} }
// fallback - if only callback is given // fallback - if only callback is given
if (isFunction(all) && !callback) { if (isFunction(all) && !callback) {
callback = all; callback = all;
@ -2655,7 +2694,7 @@ function dockerContainers(all, callback) {
if (callback) { callback(NOT_SUPPORTED) } if (callback) { callback(NOT_SUPPORTED) }
reject(error); reject(error);
} }
let cmd = "curl --unix-socket /var/run/docker.sock http:/containers/json" + (all ? "?all=1": ""); let cmd = "curl --unix-socket /var/run/docker.sock http:/containers/json" + (all ? "?all=1" : "");
exec(cmd, function (error, stdout) { exec(cmd, function (error, stdout) {
if (!error) { if (!error) {
try { try {
@ -2756,8 +2795,8 @@ function docker_calcNetworkIO(networks) {
* @property {number} tx_bytes * @property {number} tx_bytes
*/ */
var obj = networks[key]; var obj = networks[key];
rx =+ obj.rx_bytes; rx = +obj.rx_bytes;
tx =+ obj.tx_bytes; tx = +obj.tx_bytes;
} }
return { return {
rx: rx, rx: rx,
@ -2775,8 +2814,8 @@ function docker_calcBlockIO(blkio_stats) {
* @namespace * @namespace
* @property {Array} io_service_bytes_recursive * @property {Array} io_service_bytes_recursive
*/ */
if (blkio_stats && blkio_stats.io_service_bytes_recursive && Object.prototype.toString.call( blkio_stats.io_service_bytes_recursive ) === '[object Array]' && blkio_stats.io_service_bytes_recursive.length > 0) { if (blkio_stats && blkio_stats.io_service_bytes_recursive && Object.prototype.toString.call(blkio_stats.io_service_bytes_recursive) === '[object Array]' && blkio_stats.io_service_bytes_recursive.length > 0) {
blkio_stats.io_service_bytes_recursive.forEach( function(element) { blkio_stats.io_service_bytes_recursive.forEach(function (element) {
/** /**
* @namespace * @namespace
* @property {string} op * @property {string} op
@ -2875,9 +2914,9 @@ function dockerAll(callback) {
reject(error); reject(error);
} }
dockerContainers(true).then(result => { dockerContainers(true).then(result => {
if (result && Object.prototype.toString.call( result ) === '[object Array]' && result.length > 0) { if (result && Object.prototype.toString.call(result) === '[object Array]' && result.length > 0) {
var l = result.length; var l = result.length;
result.forEach( function(element) { result.forEach(function (element) {
dockerContainerStats(element.id).then(res => { dockerContainerStats(element.id).then(res => {
// include stats in array // include stats in array
element.mem_usage = res.mem_usage; element.mem_usage = res.mem_usage;
@ -2932,6 +2971,8 @@ function getStaticData(callback) {
data.system = res; data.system = res;
osInfo().then(res => { osInfo().then(res => {
data.os = res; data.os = res;
versions().then(res => {
data.versions = res;
cpu().then(res => { cpu().then(res => {
data.cpu = res; data.cpu = res;
graphics().then(res => { graphics().then(res => {
@ -2945,6 +2986,7 @@ function getStaticData(callback) {
}) })
}) })
}) })
})
}); });
}); });
} }