#!/usr/bin/perl use strict; use warnings; use utf8; use open qw(:utf8 :std); use File::Basename; my $SN = shift || 'WD-WCAWZ0066252'; my $lh; sub say { my $what = "@_"; chomp $what; if( !defined $lh ) { open $lh, '>>', basename( $0, '.pl' ) . '-' . $SN . '.log' or $lh = 0; } for( split /\r?\n/, $what ) { next if !/\S/; # s/^\s+//s; s/\s+$//s; my $row = ~~ localtime . ' ' . $_ . "\n"; print $row; print $lh $row if $lh; } } 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; } say 'Disk', $SN, 'found at', $disk; say qx/smartctl -A $disk/; 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; my $sre = qr"@{[ join q{|}, qw(4 5 9 10 11 12 192 193 194 196 197 198) ]}"; sub check_smart_events { for(qx/smartctl -A $disk/) { /^\s*($sre)\s+(\S+).+\s+(\d+)\s*$/ or next; my( $id, $name, $val ) = ( $1, $2, $3 ); next if defined $sev{$id} && $sev{$id} == $val; #say $name . '(' . $id . ')', ( defined $sev{$id} ? 'value changed to' : '=' ), $val; if( defined $sev{$id} ) { say $name . '(' . $id . ')', 'value changed from', $sev{$id}, '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; print 'For 3″ you can use ^C gracefully ;-)', "\n"; sleep 3; }