diskLayout() added S.M.A.R.T. status

This commit is contained in:
Sebastian Hildebrandt 2018-09-04 13:38:07 +02:00
parent f424ceee3c
commit 68d0d1427f
4 changed files with 106 additions and 11 deletions

View File

@ -100,6 +100,7 @@ Other changes
| Version | Date | Comment |
| -------------- | -------------- | -------- |
| 3.45.0 | 2018-09-04 | `diskLayout()` added smartStatus |
| 3.44.2 | 2018-08-28 | added code quality badges |
| 3.44.1 | 2018-08-28 | code cleanup |
| 3.44.0 | 2018-08-25 | `battery()` bugfix & added type, model, manufacturer, serial |

View File

@ -56,13 +56,13 @@ async function cpu() {
(last 7 major and minor version releases)
- Version 3.45.0: `diskLayout()` added S.M.A.R.T. status
- Version 3.44.0: `battery()` added type, model, manufacturer, serial, timeremaining
- Version 3.43.0: added speed per CPU core `cpuCurrentspeed()`
- Version 3.42.0: added parent process PID `processes()`
- Version 3.41.0: first partial `SunOS` support
- Version 3.40.0: extended `versions()` (php, redis, mongodb)
- Version 3.39.0: added `versions().mysql` and `versions().nginx`, start implementing `SunOS` support
- Version 3.38.0: added `battery.acconnected`
- ...
You can find all changes here: [detailed changelog][changelog-url]
@ -193,6 +193,7 @@ I also created a nice little command line tool called [mmon][mmon-github-url] (
| | [0].sectorsPerTrack | | | | X | | sectors per track |
| | [0].totalSectors | | | | X | | total sectors |
| | [0].bytesPerSector | | | | X | | bytes per sector |
| | [0].smartStatus | X | | X | X | | S.M.A.R.T Status (see Known Issues) |
| si.battery(cb) | {...} | X | X | X | X | | battery information |
| | hasbattery | X | X | X | X | | indicates presence of battery |
| | cyclecount | X | | X | | | numbers of recharges |
@ -518,6 +519,10 @@ In some cases we also discovered that `wmic` returned incorrect temperature valu
In some cases you need to install the linux `sensors` package to be able to measure temperature
e.g. on DEBIAN based systems by running `sudo apt-get install lm-sensors`
#### Linux S.M.A.R.T. Status
To be able to detect S.M.A.R.T. status on Linux you need to install `smartmontools`. On DEBIAN based linux distributions you can install it by running `sudo apt-get install smartmontools`
## *: Additional Notes
In `fsStats`, `disksIO` and `networkStats` the `results / sec.` values (rx_sec, IOPS, ...) are calculated correctly beginning

View File

@ -608,6 +608,7 @@ function diskLayout(callback) {
process.nextTick(() => {
let result = [];
let cmd = '';
if (_linux) {
exec('export LC_ALL=C; lshw -class disk; unset LC_ALL', function (error, stdout) {
@ -617,6 +618,7 @@ function diskLayout(callback) {
devices.forEach(function (device) {
let lines = device.split('\n');
let mediumType = '';
const BSDName = util.getValue(lines, 'logical name', ':', true).trim();
const logical = util.getValue(lines, 'logical name', ':', true).trim().replace(/\/dev\//g, '');
try {
mediumType = execSync('cat /sys/block/' + logical + '/queue/rotational').toString().split('\n')[0];
@ -642,14 +644,53 @@ function diskLayout(callback) {
firmwareRevision: util.getValue(lines, 'version:', ':', true).trim(),
serialNum: util.getValue(lines, 'serial:', ':', true).trim(),
interfaceType: '',
smartStatus: 'unknown',
BSDName: BSDName
});
cmd = cmd + 'printf "\n' + BSDName + '|"; smartctl -H ' + BSDName + ' | grep overall;';
}
});
}
if (callback) {
callback(result);
if (cmd) {
cmd = cmd + 'printf "\n"';
exec(cmd, function (error, stdout) {
let lines = stdout.toString().split('\n');
lines.forEach(line => {
if (line) {
let parts = line.split('|');
if (parts.length === 2) {
let BSDName = parts[0];
parts[1] = parts[1].trim();
let parts2 = parts[1].split(':');
if (parts2.length === 2) {
parts2[1] = parts2[1].trim();
let status = parts2[1].toLowerCase();
for (let i = 0; i < result.length; i++) {
if (result[i].BSDName === BSDName) {
result[i].smartStatus = (status === 'passed' ? 'Ok' : (status === 'failed!' ? 'Predicted Failure' : 'unknown'));
}
}
}
}
}
});
for (let i = 0; i < result.length; i++) {
delete result[i].BSDName;
}
if (callback) {
callback(result);
}
resolve(result);
});
} else {
for (let i = 0; i < result.length; i++) {
delete result[i].BSDName;
}
if (callback) {
callback(result);
}
resolve(result);
}
resolve(result);
});
}
if (_freebsd || _openbsd) {
@ -673,6 +714,7 @@ function diskLayout(callback) {
let lines = device.split('\n');
const mediumType = util.getValue(lines, 'Medium Type', ':', true).trim();
const sizeStr = util.getValue(lines, 'capacity', ':', true).trim();
const BSDName = util.getValue(lines, 'BSD Name', ':', true).trim();
if (sizeStr) {
let sizeValue = 0;
if (sizeStr.indexOf('(') >= 0) {
@ -696,8 +738,11 @@ function diskLayout(callback) {
sectorsPerTrack: -1,
firmwareRevision: util.getValue(lines, 'Revision', ':', true).trim(),
serialNum: util.getValue(lines, 'Serial Number', ':', true).trim(),
interfaceType: util.getValue(lines, 'InterfaceType', ':', true).trim()
interfaceType: util.getValue(lines, 'InterfaceType', ':', true).trim(),
smartStatus: 'unknown',
BSDName: BSDName
});
cmd = cmd + 'printf "\n' + BSDName + '|"; diskutil info /dev/' + BSDName + ' | grep SMART;';
}
}
});
@ -709,6 +754,7 @@ function diskLayout(callback) {
let lines = device.split('\n');
const linkWidth = util.getValue(lines, 'link width', ':', true).trim();
const sizeStr = util.getValue(lines, '!capacity', ':', true).trim();
const BSDName = util.getValue(lines, 'BSD Name', ':', true).trim();
if (sizeStr) {
let sizeValue = 0;
if (sizeStr.indexOf('(') >= 0) {
@ -733,16 +779,55 @@ function diskLayout(callback) {
firmwareRevision: util.getValue(lines, 'Revision', ':', true).trim(),
serialNum: util.getValue(lines, 'Serial Number', ':', true).trim(),
interfaceType: ('PCIe ' + linkWidth).trim(),
smartStatus: 'unknown',
BSDName: BSDName
});
cmd = cmd + 'printf "\n' + BSDName + '|"; diskutil info /dev/' + BSDName + ' | grep SMART;';
}
}
});
}
}
if (callback) {
callback(result);
if (cmd) {
cmd = cmd + 'printf "\n"';
exec(cmd, function (error, stdout) {
let lines = stdout.toString().split('\n');
lines.forEach(line => {
if (line) {
let parts = line.split('|');
if (parts.length === 2) {
let BSDName = parts[0];
parts[1] = parts[1].trim();
let parts2 = parts[1].split(':');
if (parts2.length === 2) {
parts2[1] = parts2[1].trim();
let status = parts2[1].toLowerCase();
for (let i = 0; i < result.length; i++) {
if (result[i].BSDName === BSDName) {
result[i].smartStatus = (status === 'not supported' ? 'not supported' : (status === 'verified' ? 'Ok' : (status === 'failing' ? 'Predicted Failure' : 'unknown')));
}
}
}
}
}
});
for (let i = 0; i < result.length; i++) {
delete result[i].BSDName;
}
if (callback) {
callback(result);
}
resolve(result);
});
} else {
for (let i = 0; i < result.length; i++) {
delete result[i].BSDName;
}
if (callback) {
callback(result);
}
resolve(result);
}
resolve(result);
});
}
if (_windows) {
@ -753,6 +838,7 @@ function diskLayout(callback) {
devices.forEach(function (device) {
let lines = device.split('\r\n');
const size = util.getValue(lines, 'Size', '=').trim();
const status = util.getValue(lines, 'Status', '=').trim();
if (size) {
result.push({
type: device.indexOf('SSD') > -1 ? 'SSD' : 'HD', // not really correct(!) ... maybe this one is better: MSFT_PhysicalDisk - Media Type??
@ -768,7 +854,8 @@ function diskLayout(callback) {
sectorsPerTrack: parseInt(util.getValue(lines, 'SectorsPerTrack', '=')),
firmwareRevision: util.getValue(lines, 'FirmwareRevision', '=').trim(),
serialNum: util.getValue(lines, 'SerialNumber', '=').trim(),
interfaceType: util.getValue(lines, 'InterfaceType', '=').trim()
interfaceType: util.getValue(lines, 'InterfaceType', '=').trim(),
smartStatus: (status === 'Ok' ? 'Ok' : (status === 'Degraded' ? 'Degraded' : (status === 'Pred Fail' ? 'Predicted Failure' : 'Unknown')))
});
}
});

View File

@ -40,7 +40,9 @@
"graphics",
"graphic card",
"graphic controller",
"display"
"display",
"smart",
"disk layout"
],
"repository": {
"type": "git",
@ -57,4 +59,4 @@
"engines": {
"node": ">=4.0.0"
}
}
}