better output while relocating sectors
[sysadmin-cookbook] / recepies / smart / smart-test-relocate.pl
1 #!/usr/bin/perl
2
3 use warnings;
4 use strict;
5
6 my $drive = $ARGV[0] || die "usage: $0 /dev/sda\n";
7 my $delay = 15;
8 my $rewrite_sectors = 16;
9
10 my $test_started = 0;
11
12 sub smart_test {
13         my $sector = shift;
14         my $cmd = "smartctl -t select,$sector-max $drive";
15         warn "$cmd\n";
16         system $cmd;
17         $test_started = 1;
18 }
19
20 sub smart {
21         my $cmd = "smartctl -l selective $drive";
22         warn "$cmd\n";
23         open(my $fh, '-|', $cmd);
24         while(<$fh>) {
25                 chomp;
26                 print "# $_\n";
27                 if ( m/Completed_read_failure.*\((\d+)-\d+\)/ ) {
28                         my $sector = $1;
29                         print "rewrite sector: $sector\n";
30                         foreach my $s ( $sector .. $sector + $rewrite_sectors ) {
31                                 system "hdparm --write-sector $s --yes-i-know-what-i-am-doing $drive";
32                         }
33                         smart_test $sector;
34                         return 1;
35                 } elsif ( m/Self_test_in_progress/ ) {
36                         $test_started = 1;
37                         return 1;
38                 } elsif ( m/Not_testing/ ) {
39                         return 1 if $test_started;
40                         smart_test 0; # first-time invocation
41                 }
42         }
43         return 0;
44 }
45
46 while ( smart ) {
47         warn "sleep $delay s", ( $test_started ? " smart test running..." : "idle" ), "\n";
48         sleep $delay;
49 }