diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..484ab7e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +results/* diff --git a/smart_stats b/smart_stats new file mode 100755 index 0000000..87d4a45 --- /dev/null +++ b/smart_stats @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 + +import json +import os +import pprint +import subprocess +import sys + +def do(cmd): + p = subprocess.run(cmd, check=False, capture_output=True, encoding='UTF-8') + return (p.stdout, p.stderr, p.returncode) + + +def get_drives(): + drives = [] + cmd = ['lsblk', '-J'] + stdout, stderr, exit_code = do(cmd) + if stderr or exit_code != 0: + sys.exit(f'error: {stderr}') + drive_data = json.loads(stdout) + try: + bds = drive_data['blockdevices'] + except KeyError: + sys.exit('No fucking drives') + for drive in bds: + drives.append(drive['name']) + return drives + + +# TODO(luket): add exit code parsing +# +# Bit 0: Command line did not parse. +# Bit 1: Device open failed, device did not return an IDENTIFY DEVICE structure, or device is in a low-power mode (see '-n' option above). +# Bit 2: Some SMART or other ATA command to the disk failed, or there was a checksum error in a SMART data structure (see '-b' option above). +# Bit 3: SMART status check returned "DISK FAILING". +# Bit 4: We found prefail Attributes <= threshold. +# Bit 5: SMART status check returned "DISK OK" but we found that some (usage or prefail) Attributes have been <= threshold at some time in the past. +# Bit 6: The device error log contains records of errors. +# Bit 7: The device self-test log contains records of errors. [ATA only] Failed self-tests outdated by a newer successful extended self-test are ignored. + +def get_smart(drives): + if os.getuid() != 0: + sys.exit('Need to be root to get smart.') + for drive in drives: + drive_path = f'/dev/{drive}' + cmd = ['/usr/bin/smartctl', '--json', '-a', drive_path] + stdout, stderr, exit_code = do(cmd) + drive_data = json.loads(stdout) + pprint.pprint(drive_data) + + +def main(): + get_smart(get_drives()) + +if __name__ == '__main__': + main()