SMART.pm 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. package Disk::SMART;
  2. {
  3. $Disk::SMART::VERSION = '0.03.1'
  4. }
  5. =head1 NAME
  6. Disk::SMART - Provides an interface to smartctl
  7. =head1 SYNOPSIS
  8. Disk::SMART is an object ooriented module that provides an interface to get SMART disk info from a device as well as initiate testing.
  9. use Disk::SMART;
  10. my $smart = Disk::SMART->new('/dev/sda');
  11. =cut
  12. use warnings;
  13. use strict;
  14. use Carp;
  15. use Math::Round;
  16. =head1 CONSTRUCTOR
  17. =head2 B<new (DEVICE)>
  18. Instantiates the Disk::SMART object
  19. C<DEVICE> - Device identifier of SSD / Hard Drive
  20. my $smart = Disk::SMART->new( 'dev/sda', '/dev/sdb' );
  21. Returns C<Disk::SMART> object if smartctl is available and can poll the given device.
  22. =cut
  23. sub new {
  24. my ( $class, @devices ) = @_;
  25. my $smartctl = '/usr/sbin/smartctl';
  26. my $self = bless {}, $class;
  27. croak "Valid device identifier not supplied to constructor for $class.\n" if ( !@devices );
  28. croak "smartctl binary was not found on your system, are you running as root?\n" if !-f $smartctl;
  29. foreach my $device (@devices) {
  30. my $out = qx($smartctl -a $device);
  31. if ( $out =~ /No such device/i ) {
  32. croak "Smartctl couldn't poll device $device\n";
  33. }
  34. $self->{'devices'}->{$device}->{'SMART_OUTPUT'} = $out;
  35. }
  36. return $self;
  37. }
  38. =head1 USER METHODS
  39. =head2 B<get_disk_temp (DEVICE)>
  40. Returns an array with the temperature of the device in Celsius and Farenheit, or N/A.
  41. C<DEVICE> - Device identifier of SSD / Hard Drive
  42. my ($temp_c, $temp_f) = $smart->get_disk_temp('/dev/sda');
  43. =cut
  44. sub get_disk_temp {
  45. my ( $self, $device ) = @_;
  46. $self->_validate_param($device);
  47. my $smart_output = $self->{'devices'}->{$device}->{'SMART_OUTPUT'};
  48. my ($temp_c) = $smart_output =~ /(Temperature_Celsius.*\n)/;
  49. if ( !defined $temp_c || $smart_output =~ qr/S.M.A.R.T. not available/x ) {
  50. return 'N/A';
  51. }
  52. chomp $temp_c;
  53. $temp_c =~ s/ //g;
  54. $temp_c =~ s/.*-//;
  55. $temp_c =~ s/\(.*\)//;
  56. my $temp_f = round( ( $temp_c * 9 ) / 5 + 32 );
  57. return ( $temp_c, $temp_f );
  58. }
  59. =head2 B<get_disk_health (DEVICE)>
  60. Returns the health of the disk. Output is "PASSED", "FAILED", or "N/A".
  61. C<DEVICE> - Device identifier of SSD / Hard Drive
  62. my $disk_health = $smart->get_disk_health('/dev/sda');
  63. =cut
  64. sub get_disk_health {
  65. my ( $self, $device ) = @_;
  66. $self->_validate_param($device);
  67. my $smart_output = $self->{'devices'}->{$device}->{'SMART_OUTPUT'};
  68. my ($health) = $smart_output =~ /(SMART overall-health self-assessment.*\n)/;
  69. if ( (!defined $health) or $health !~ /PASSED|FAILED/x ) {
  70. return 'N/A';
  71. }
  72. $health =~ s/.*: //;
  73. chomp $health;
  74. return $health;
  75. }
  76. =head2 B<get_disk_model (DEVICE)>
  77. Returns the model of the device. eg. "ST3250410AS".
  78. C<DEVICE> - Device identifier of SSD / Hard Drive
  79. my $disk_model = $smart->get_disk_model('/dev/sda');
  80. =cut
  81. sub get_disk_model {
  82. my ( $self, $device ) = @_;
  83. $self->_validate_param($device);
  84. my $smart_output = $self->{'devices'}->{$device}->{'SMART_OUTPUT'};
  85. my ($model) = $smart_output =~ /(Device\ Model.*\n)/;
  86. if ( !defined $model ) {
  87. return 'N/A';
  88. }
  89. $model =~ s/.*:\ //;
  90. $model =~ s/^\s+|\s+$//g; #trim beginning and ending whitepace
  91. return $model;
  92. }
  93. =head2 B<get_disk_errors (DEVICE)>
  94. Returns any listed errors
  95. C<DEVICE> - DEvice identifier of SSD/ Hard Drive
  96. my $disk_errors = $smart->get_disk_errors('/dev/sda');
  97. =cut
  98. sub get_disk_errors {
  99. my ( $self, $device ) = @_;
  100. $self->_validate_param($device);
  101. my $smart_output = $self->{'devices'}->{$device}->{'SMART_OUTPUT'};
  102. my ($errors) = $smart_output =~ /SMART Error Log Version: [1-9](.*)SMART Self-test log/s;
  103. if ( !defined $errors ) {
  104. return 'N/A';
  105. }
  106. $errors =~ s/^\s+|\s+$//g; #trim beginning and ending whitepace
  107. return $errors;
  108. }
  109. sub _validate_param {
  110. my ( $self, $device ) = @_;
  111. croak "$device not found in object, You probably didn't enter it right" if ( !exists $self->{'devices'}->{$device} );
  112. }
  113. 1;
  114. __END__
  115. =head1 AUTHOR
  116. Paul Trost <ptrost@cpan.org>
  117. =head1 LICENSE AND COPYRIGHT
  118. Copyright 2014 by Paul Trost
  119. This script is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License v2, or at your option any later version.
  120. <http://gnu.org/licenses/gpl.html>
  121. =cut