#!/usr/bin/perl use strict; use warnings; my $SN = 'WD-WCAWZ0066252'; sub say { my $what = "@_"; for($what) { s/^\s+//s; s/\s+$//s; } print ~~ localtime, " $what\n"; } my $disk; for(qx/udisksctl status/) { /\b$SN\s+(\S+)/ or next; $disk = '/dev/' . $1; last; } if( !$disk || -f $disk ) { say 'Disk', $SN, 'not found.'; exit 2; } sub is_test_in_progress { for(qx/smartctl -c $disk/) { /^Self-test execution status.+progress/ and return 1; } return 0; } sub sector_check { my($sector) = @_; for(qx/hdparm --read-sector $sector $disk/) { /^reading/ or next; say 'Checked with hdparm:', $_; last; } } my %sev; sub check_smart_events { for(qx/smartctl -A $disk/) { /^(19[678])\s+(\S+).+\s+(\d+)\s*$/ or next; my( $id, $name, $val ) = ( $1, $2, $3 ); next if defined $sev{$id} && $sev{$id} == $val; say $name, ( defined $sev{$id} ? 'value changed to' : '=' ), $val; $sev{$id} = $val; } } check_smart_events; my $t = 0; while(1) { $t++; my $test_running = 0; for(qx/smartctl -t short $disk/) { /has begun/ or next; say 'T#' . $t, $_; $test_running = 1; last; } exit $? if !$test_running; sleep 10 while is_test_in_progress; for(qx/smartctl -l selftest $disk/) { /^# 1\s+Short offline\s+(.+?)\s+\d+%\s+\d+\s+(-|\d+)/ or next; my( $status, $lba ) = ( $1, $2 ); say 'T#' . $t, 'Test', $status, $lba ne '-' ? '(LBA sector ' . $lba . ')' : q{}; sector_check($lba) if $lba ne '-'; last; } check_smart_events; }