瀏覽代碼

Updated POD. Added extended output to get_disk_health

Paul Trost 11 年之前
父節點
當前提交
7da15f9aa9
共有 4 個文件被更改,包括 42 次插入7 次删除
  1. 4 2
      Changes
  2. 二進制
      dist/Disk-SMART-0.11.tar.gz
  3. 34 4
      lib/Disk/SMART.pm
  4. 4 1
      t/01-function_tests.t

+ 4 - 2
Changes

@@ -1,7 +1,9 @@
 Revision history for Disk-SMART
 Revision history for Disk-SMART
 
 
-0.11	2014
-	Updated POD for update_data() and run_short_test()
+0.11	2014-11-24
+	Updated POD
+	Code cleanup.
+	Added extended output to get_disk_health() that will report any values > 1 from specific attributes that show impending drive failure
 
 
 0.10	2014-10-18
 0.10	2014-10-18
 	Updated regex to get disk temperature to look for two different lines that could contain temp
 	Updated regex to get disk temperature to look for two different lines that could contain temp

二進制
dist/Disk-SMART-0.11.tar.gz


+ 34 - 4
lib/Disk/SMART.pm

@@ -97,7 +97,24 @@ sub get_disk_errors {
 
 
 =head2 B<get_disk_health(DEVICE)>
 =head2 B<get_disk_health(DEVICE)>
 
 
-Returns the health of the disk. Output is "PASSED", "FAILED", or "N/A".
+Returns the health of the disk. Output is "PASSED", "FAILED", or "N/A". If the device has positive values for the attributes listed below then the status will output that information.
+
+Eg. "FAILED - Reported_Uncorrectable_Errors = 1"
+
+The attributes are:
+
+5 - Reallocated_Sector_Count
+
+187 - Reported_Uncorrectable_Errors
+
+188 - Command_Timeout
+
+197 - Current_Pending_Sector_Count
+
+198 - Offline_Uncorrectable
+
+If Reported_Uncorrectable_Errors is greater than 0 then the drive should be replaced immediately. This list is taken from a study shown at https://www.backblaze.com/blog/hard-drive-smart-stats/
+
 
 
 C<DEVICE> - Device identifier of SSD / Hard Drive
 C<DEVICE> - Device identifier of SSD / Hard Drive
 
 
@@ -109,7 +126,17 @@ sub get_disk_health {
     my ( $self, $device ) = @_;
     my ( $self, $device ) = @_;
     $self->_validate_param($device);
     $self->_validate_param($device);
 
 
-    return $self->{'devices'}->{$device}->{'health'};
+    my $status = $self->{'devices'}->{$device}->{'health'};
+
+    my %failure_attribute_hash;
+    while ( my ($key, $value) = each %{ $self->{'devices'}->{$device}->{'attributes'} } ) {
+        if ( $key =~ /\A5\Z|\A187\Z|\A188\Z|\A197\Z|\A198\Z/ ) {
+            $failure_attribute_hash{$key} = $value;
+            $status .= ": $key - $value->[0] = $value->[1]" if ( $value->[1] > 0 );
+        }
+    }
+
+    return $status;
 }
 }
 
 
 
 
@@ -219,14 +246,16 @@ sub _process_disk_attributes {
     my $smart_output = $self->{'devices'}->{$device}->{'SMART_OUTPUT'};
     my $smart_output = $self->{'devices'}->{$device}->{'SMART_OUTPUT'};
     my ($smart_attributes) = $smart_output =~ /(ID# ATTRIBUTE_NAME.*)\nSMART Error/s;
     my ($smart_attributes) = $smart_output =~ /(ID# ATTRIBUTE_NAME.*)\nSMART Error/s;
     my @attributes = split /\n/, $smart_attributes;
     my @attributes = split /\n/, $smart_attributes;
-    shift @attributes;
+    shift @attributes; #remove table header
 
 
     foreach my $attribute (@attributes) {
     foreach my $attribute (@attributes) {
+        my $id    = substr $attribute, 0,  +3;
         my $name  = substr $attribute, 4,  +24;
         my $name  = substr $attribute, 4,  +24;
         my $value = substr $attribute, 83, +50;
         my $value = substr $attribute, 83, +50;
+        $id    = _trim($id);
         $name  = _trim($name);
         $name  = _trim($name);
         $value = _trim($value);
         $value = _trim($value);
-        $self->{'devices'}->{$device}->{'attributes'}->{$name} = $value;
+        $self->{'devices'}->{$device}->{'attributes'}->{$id} = [ $name, $value ];
     }
     }
 
 
     return;
     return;
@@ -307,6 +336,7 @@ sub _validate_param {
 
 
 1;
 1;
 
 
+
 __END__
 __END__
 
 
 =head1 COMPATIBILITY
 =head1 COMPATIBILITY

+ 4 - 1
t/01-function_tests.t

@@ -1,6 +1,6 @@
 use warnings;
 use warnings;
 use strict;
 use strict;
-use Test::More 'tests' => 15;
+use Test::More 'tests' => 17;
 use Test::Fatal;
 use Test::Fatal;
 use Disk::SMART;
 use Disk::SMART;
 
 
@@ -114,8 +114,11 @@ is( keys %attribs, 18, 'get_disk_attributes() returns hash of device attributes'
 is( $smart->run_short_test($disk), 'Completed without error', 'run_short_test() returns proper string' );
 is( $smart->run_short_test($disk), 'Completed without error', 'run_short_test() returns proper string' );
 
 
 $ENV{'MOCK_TEST_DATA'} =~ s/ST3250410AS//;
 $ENV{'MOCK_TEST_DATA'} =~ s/ST3250410AS//;
+$ENV{'MOCK_TEST_DATA'} =~ s/187 Reported_Uncorrect      0x0032   100   100   000    Old_age   Always       -       0/187 Reported_Uncorrect      0x0032   100   100   000    Old_age   Always       -       1/;
 is( $smart->update_data($disk), undef, 'update_data() updated object with changed device data' );
 is( $smart->update_data($disk), undef, 'update_data() updated object with changed device data' );
 is( $smart->get_disk_model($disk), 'N/A', 'get_disk_model() returns N/A with changed device data' );
 is( $smart->get_disk_model($disk), 'N/A', 'get_disk_model() returns N/A with changed device data' );
+is( $smart->get_disk_temp($disk), 2, 'get_disk_temp() returns device temperature' );
+is( $smart->get_disk_health($disk), 'PASSED: 187 - Reported_Uncorrect = 1', 'get_disk_health() returns failed attribute status when SMART attribute 187 > 0' );
 
 
 #Negative testing
 #Negative testing
 $disk  = '/dev/test_bad';
 $disk  = '/dev/test_bad';