Merge pull request #368 from mily20001/feature/smartctl
add full smart data from smartctl
This commit is contained in:
commit
2db0a99a98
@ -382,6 +382,7 @@ I also created a nice little command line tool called [mmon][mmon-github-url] (
|
|||||||
| | [0].serialNum | X | | X | X | | serial number |
|
| | [0].serialNum | X | | X | X | | serial number |
|
||||||
| | [0].interfaceType | X | | | X | | SATA, PCIe, ... |
|
| | [0].interfaceType | X | | | X | | SATA, PCIe, ... |
|
||||||
| | [0].smartStatus | X | | X | X | | S.M.A.R.T Status (see Known Issues) |
|
| | [0].smartStatus | X | | X | X | | S.M.A.R.T Status (see Known Issues) |
|
||||||
|
| | [0].smartData | X | | | | | S.M.A.R.T data from smartctl - requires at least smartmontools 7.0 (see Known Issues) |
|
||||||
| si.blockDevices(cb) | [{...}] | X | | X | X | | returns array of disks, partitions,<br>raids and roms |
|
| si.blockDevices(cb) | [{...}] | X | | X | X | | returns array of disks, partitions,<br>raids and roms |
|
||||||
| | [0].name | X | | X | X | | name |
|
| | [0].name | X | | X | X | | name |
|
||||||
| | [0].type | X | | X | X | | type |
|
| | [0].type | X | | X | X | | type |
|
||||||
|
|||||||
@ -739,6 +739,17 @@ function diskLayout(callback) {
|
|||||||
let cmd = '';
|
let cmd = '';
|
||||||
|
|
||||||
if (_linux) {
|
if (_linux) {
|
||||||
|
let cmdFullSmart = '';
|
||||||
|
const commitResult = res => {
|
||||||
|
for (let i = 0; i < res.length; i++) {
|
||||||
|
delete res[i].BSDName;
|
||||||
|
}
|
||||||
|
if (callback) {
|
||||||
|
callback(res);
|
||||||
|
}
|
||||||
|
resolve(res);
|
||||||
|
};
|
||||||
|
|
||||||
exec('export LC_ALL=C; lsblk -ablJO 2>/dev/null; unset LC_ALL', function (error, stdout) {
|
exec('export LC_ALL=C; lsblk -ablJO 2>/dev/null; unset LC_ALL', function (error, stdout) {
|
||||||
if (!error) {
|
if (!error) {
|
||||||
try {
|
try {
|
||||||
@ -789,52 +800,60 @@ function diskLayout(callback) {
|
|||||||
smartStatus: 'unknown',
|
smartStatus: 'unknown',
|
||||||
BSDName: BSDName
|
BSDName: BSDName
|
||||||
});
|
});
|
||||||
cmd = cmd + 'printf "\n' + BSDName + '|"; smartctl -H ' + BSDName + ' | grep overall;';
|
cmd += `printf "\n${BSDName}|"; smartctl -H ${BSDName} | grep overall;`;
|
||||||
|
cmdFullSmart += `${cmdFullSmart ? 'printf ",";' : ''}smartctl -a -j ${BSDName};`
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
util.noop();
|
util.noop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// check S.M.A.R.T. status
|
// check S.M.A.R.T. status
|
||||||
if (cmd) {
|
if (cmdFullSmart) {
|
||||||
cmd = cmd + 'printf "\n"';
|
exec(cmdFullSmart, function (error, stdout) {
|
||||||
exec(cmd, function (error, stdout) {
|
try {
|
||||||
let lines = stdout.toString().split('\n');
|
const data = JSON.parse(`[${stdout}]`);
|
||||||
lines.forEach(line => {
|
data.forEach(disk => {
|
||||||
if (line) {
|
const diskBSDName = disk.smartctl.argv[disk.smartctl.argv.length - 1];
|
||||||
let parts = line.split('|');
|
|
||||||
if (parts.length === 2) {
|
for (let i = 0; i < result.length; i++) {
|
||||||
let BSDName = parts[0];
|
if (result[i].BSDName === diskBSDName) {
|
||||||
parts[1] = parts[1].trim();
|
result[i].smartStatus = (disk.smart_status.passed ? 'Ok' : (disk.smart_status.passed === false ? 'Predicted Failure' : 'unknown'));
|
||||||
let parts2 = parts[1].split(':');
|
result[i].smartData = disk;
|
||||||
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'));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
commitResult(result);
|
||||||
|
} catch (e) {
|
||||||
|
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'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
commitResult(result);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
commitResult(result);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
76
lib/index.d.ts
vendored
76
lib/index.d.ts
vendored
@ -123,6 +123,81 @@ export namespace Systeminformation {
|
|||||||
voltageMax: number;
|
voltageMax: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface SmartData {
|
||||||
|
smartctl: {
|
||||||
|
version: number[];
|
||||||
|
platform_info: string;
|
||||||
|
build_info: string;
|
||||||
|
argv: string[];
|
||||||
|
exit_status: number;
|
||||||
|
};
|
||||||
|
json_format_version: number[];
|
||||||
|
device: {
|
||||||
|
name: string;
|
||||||
|
info_name: string;
|
||||||
|
type: string;
|
||||||
|
protocol: string;
|
||||||
|
}
|
||||||
|
smart_status: {
|
||||||
|
passed: boolean;
|
||||||
|
}
|
||||||
|
ata_smart_attributes: {
|
||||||
|
revision: number;
|
||||||
|
table: {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
value: number;
|
||||||
|
worst: number;
|
||||||
|
thresh: number;
|
||||||
|
when_failed: string;
|
||||||
|
flags: {
|
||||||
|
value: number;
|
||||||
|
string: string;
|
||||||
|
prefailure: boolean;
|
||||||
|
updated_online: boolean;
|
||||||
|
performance: boolean;
|
||||||
|
error_rate: boolean;
|
||||||
|
event_count: boolean;
|
||||||
|
auto_keep: boolean;
|
||||||
|
};
|
||||||
|
raw: { value: number; string: string }
|
||||||
|
}[];
|
||||||
|
};
|
||||||
|
power_on_time: {
|
||||||
|
hours: number;
|
||||||
|
};
|
||||||
|
power_cycle_count: number;
|
||||||
|
temperature: {
|
||||||
|
current: number;
|
||||||
|
};
|
||||||
|
ata_smart_error_log: {
|
||||||
|
summary: {
|
||||||
|
revision: number;
|
||||||
|
count: number;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
ata_smart_self_test_log: {
|
||||||
|
standard: {
|
||||||
|
revision: number;
|
||||||
|
table: {
|
||||||
|
type: {
|
||||||
|
value: number;
|
||||||
|
string: string;
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
value: number;
|
||||||
|
string: string;
|
||||||
|
passed: boolean;
|
||||||
|
},
|
||||||
|
lifetime_hours: number;
|
||||||
|
}[];
|
||||||
|
count: number;
|
||||||
|
error_count_total: number;
|
||||||
|
error_count_outdated: number;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
interface DiskLayoutData {
|
interface DiskLayoutData {
|
||||||
device: string;
|
device: string;
|
||||||
type: string;
|
type: string;
|
||||||
@ -140,6 +215,7 @@ export namespace Systeminformation {
|
|||||||
serialNum: string;
|
serialNum: string;
|
||||||
interfaceType: string;
|
interfaceType: string;
|
||||||
smartStatus: string;
|
smartStatus: string;
|
||||||
|
smartData?: SmartData;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface BatteryData {
|
interface BatteryData {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user