From 3e50507d925d095b7076e9d735c96db744b49899 Mon Sep 17 00:00:00 2001 From: mily20001 Date: Fri, 1 May 2020 20:07:32 +0200 Subject: [PATCH] add full smart data from smartctl --- README.md | 1 + lib/filesystem.js | 89 ++++++++++++++++++++++++++++------------------- lib/index.d.ts | 76 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 131 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index b7ad5e5..ebf5c0b 100644 --- a/README.md +++ b/README.md @@ -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].interfaceType | X | | | X | | SATA, PCIe, ... | | | [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,
raids and roms | | | [0].name | X | | X | X | | name | | | [0].type | X | | X | X | | type | diff --git a/lib/filesystem.js b/lib/filesystem.js index 6790a39..be670ee 100755 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -739,6 +739,17 @@ function diskLayout(callback) { let cmd = ''; 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) { if (!error) { try { @@ -789,52 +800,60 @@ function diskLayout(callback) { smartStatus: 'unknown', 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) { util.noop(); } } // check S.M.A.R.T. status - 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')); - } + if (cmdFullSmart) { + exec(cmdFullSmart, function (error, stdout) { + try { + const data = JSON.parse(`[${stdout}]`); + data.forEach(disk => { + const diskBSDName = disk.smartctl.argv[disk.smartctl.argv.length - 1]; + + for (let i = 0; i < result.length; i++) { + if (result[i].BSDName === diskBSDName) { + result[i].smartStatus = (disk.smart_status.passed ? 'Ok' : (disk.smart_status.passed === false ? 'Predicted Failure' : 'unknown')); + result[i].smartData = disk; } } - } + }); + 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); } }); } diff --git a/lib/index.d.ts b/lib/index.d.ts index 74169d2..6f66e5f 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -123,6 +123,81 @@ export namespace Systeminformation { 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 { device: string; type: string; @@ -140,6 +215,7 @@ export namespace Systeminformation { serialNum: string; interfaceType: string; smartStatus: string; + smartData?: SmartData; } interface BatteryData {