#!/usr/bin/env python3 import re, os from subprocess import getoutput keys = [ "ECC corrected fast", "ECC corrected delayed", "ECC reread/rewrites", "Total errors corrected", "Correction algorithm invocations", "Gigabytes processed [10^9 bytes]", "Total uncorrected errors", ] def log(type, disk, message): print("!!LOG", type, disk, message) def get_all_scsi_path(): disks = os.listdir('/dev/disk/by-id/') out = [] for disk in disks: if disk.startswith('scsi') and 'part' not in disk: out.append('/dev/disk/by-id/'+disk) return out def call_smart(disks): out = {} for disk in disks: content = getoutput('smartctl -a {}'.format(disk)) content = parse_out(content, disk) out[disk] = content return out def save_status(stats): for disk in status: for key in ['read', 'write', 'verify']: if len(disk[key]) == 7: db.add_status(disk, key, disk[key], disk['Non-medium error count']) else: log('missing', disk, '{} is missing values'.fotmat(key)) def parse_out(content, disk=''): out = { 'read': {}, 'write': {}, 'verify': {}, 'Non-medium error count': 0, 'Elements in grown defect list': 0, 'SMART Health Status': '' } try: out['SMART Health Status'] = re.search( r'SMART Health Status:\s+(?P.+)', content ).group('status') except AttributeError as error: log('missing', disk, "SMART Health Status not found") try: out['Elements in grown defect list'] = re.search( r'Elements in grown defect list:\s+(?P\d+)', content ).group('number') except AttributeError as error: log('missing', disk, "Elements in grown defect list not found") try: out['Non-medium error count'] = re.search( r'Non-medium error count:\s+(?P\d+)', content ).group('number') except AttributeError as error: log('missing', disk, "Non-medium error count not found") try: content = content.split("Error counter log:")[1] except IndexError: log('failed', disk, 'Missing error information section') return {} for line in content.split('\n'): if line.startswith('read:'): line = re.sub(r'^[a-z:\s]+', '', line) line = re.split(r'\s+', line) out['read'] = dict(zip(keys, line)) continue if line.startswith('write:'): line = re.sub(r'^[a-z:\s]+', '', line) line = re.split(r'\s+', line) out['write'] = dict(zip(keys, line)) continue if line.startswith('verify:'): line = re.sub(r'^[a-z:\s]+', '', line) line = re.split(r'\s+', line) out['verify'] = dict(zip(keys, line)) continue return out if __name__ == "__main__": import json disks = get_all_scsi_path() parsed = call_smart(disks) print(json.dumps(parsed, indent=4, sort_keys=True)) print(*[(i,parsed[i].get('SMART Health Status')) for i in parsed], sep='\n')