diff --git a/.bin/Scripts/ddrescue-tui-smart-display b/.bin/Scripts/ddrescue-tui-smart-display deleted file mode 100755 index 4b8afcde..00000000 --- a/.bin/Scripts/ddrescue-tui-smart-display +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/python3 -# -## Wizard Kit: SMART attributes display for ddrescue TUI - -import os -import sys -import time - -# Init -os.chdir(os.path.dirname(os.path.realpath(__file__))) -sys.path.append(os.getcwd()) -from functions.hw_diags import * -init_global_vars(silent=True) - -if __name__ == '__main__': - try: - # Prep - state = State() - state.init() - - # Find disk - disk = None - for d in state.disks: - if d.path == sys.argv[1]: - disk = d - - # Show details - if disk: - for line in disk.generate_attribute_report(timestamp=True): - print(line) - else: - print_error('Disk "{}" not found'.format(sys.argv[1])) - - # Done - exit_script() - except SystemExit: - pass - except: - major_exception() - -# vim: sts=2 sw=2 ts=2 diff --git a/.bin/Scripts/functions/ddrescue.py b/.bin/Scripts/functions/ddrescue.py index 6cbc9430..00fb35f7 100644 --- a/.bin/Scripts/functions/ddrescue.py +++ b/.bin/Scripts/functions/ddrescue.py @@ -11,6 +11,7 @@ import time from collections import OrderedDict from functions.common import * from functions.data import * +from functions.hw_diags import * from functions.tmux import * from operator import itemgetter @@ -291,6 +292,7 @@ class RecoveryState(): self.total_size = 0 if mode not in ('clone', 'image'): raise GenericError('Unsupported mode') + self.get_smart_source() def add_block_pair(self, source, dest): """Run safety checks and append new BlockPair to internal list.""" @@ -349,6 +351,14 @@ class RecoveryState(): min_percent = min(min_percent, bp.rescued_percent) return min_percent + def get_smart_source(self): + """Get source for SMART dispay.""" + disk_path = self.source.path + if self.source.parent: + disk_path = self.source.parent + + self.smart_source = DiskObj(disk_path) + def retry_all_passes(self): """Mark all passes as pending for all block-pairs.""" self.finished = False @@ -951,16 +961,13 @@ def run_ddrescue(state, pass_settings): pause('Press Enter to return to main menu...') return - # Show SMART status - smart_dev = state.source_path - if state.source.parent: - smart_dev = state.source.parent - smart_cmd = [ - 'watch', '--color', '--no-title', '--interval', '5', - 'ddrescue-tui-smart-display', smart_dev, - ] + # Create SMART monitor pane + state.smart_out = '{}/smart_{}.out'.format( + global_vars['TmpDir'], state.smart_source.name) + with open(state.smart_out, 'w') as f: + f.write('Initializing...') state.panes['SMART'] = tmux_split_window( - behind=True, lines=12, vertical=True, command=smart_cmd) + behind=True, lines=12, vertical=True, watch=state.smart_out) # Show systemd journal output state.panes['Journal'] = tmux_split_window( @@ -997,10 +1004,26 @@ def run_ddrescue(state, pass_settings): clear_screen() print_info('Current dev: {}'.format(bp.source_path)) ddrescue_proc = popen_program(cmd) + i = 0 while True: + # Update SMART display (every 30 seconds) + i += 1 + if i % 30 == 0: + state.smart_source.get_smart_details() + with open(state.smart_out, 'w') as f: + report = state.smart_source.generate_attribute_report( + timestamp=True) + for line in report: + f.write('{}\n'.format(line)) + + # Update progress bp.update_progress(state.current_pass) update_sidepane(state) + + # Fix panes fix_tmux_panes(state) + + # Check if ddrescue has finished try: ddrescue_proc.wait(timeout=1) sleep(2) @@ -1008,8 +1031,9 @@ def run_ddrescue(state, pass_settings): update_sidepane(state) break except subprocess.TimeoutExpired: - # Catch to update bp/sidepane + # Catch to update smart/bp/sidepane pass + except KeyboardInterrupt: # Catch user abort pass