Disk-SMART

 view release on metacpan or  search on metacpan

lib/Disk/SMART.pm  view on Meta::CPAN

    $self->_validate_param($device);

    return $self->{'devices'}->{$device}->{'model'};
}

=head2 B<get_disk_temp(DEVICE)>

Returns an array with the temperature of the device in Celsius and Farenheit, or N/A.

C<DEVICE> - Device identifier of a single SSD / Hard Drive

    my ($temp_c, $temp_f) = $smart->get_disk_temp('/dev/sda');

=cut

sub get_disk_temp {
    my ( $self, $device ) = @_;
    $self->_validate_param($device);

    return @{ $self->{'devices'}->{$device}->{'temp'} };
}

=head2 B<run_short_test(DEVICE)>

Runs the SMART short self test and returns the result.

C<DEVICE> - Device identifier of SSD/ Hard Drive

    $smart->run_short_test('/dev/sda');

=cut

sub run_short_test {
    my ( $self, $device ) = @_;
    $self->_validate_param($device);

    my $test_out = get_smart_output( $device, '-t short' );
    my ($short_test_time) = $test_out =~ /Please wait (.*) minutes/s;
    sleep( $short_test_time * 60 );

    my $smart_output = _get_smart_output( $device, '-a' );
    ($smart_output) = $smart_output =~ /(SMART Self-test log.*)\nSMART Selective self-test/s;
    my @device_tests      = split /\n/, $smart_output;
    my $short_test_number = $device_tests[2];
    my $short_test_status = substr $short_test_number, 25, +30;
    $short_test_status = _trim($short_test_status);

    return $short_test_status;
}

=head2 B<update_data(DEVICE)>

Updates the SMART output and attributes for each device. Returns undef.

C<DEVICE> - Device identifier of a single SSD / Hard Drive or a list of devices. If none are specified then get_disk_list() is called to detect devices.

    $smart->update_data('/dev/sda');

=cut

sub update_data {
    my ( $self, @p_devices ) = @_;
    my @devices = @p_devices ? @p_devices : $self->get_disk_list();

    foreach my $device (@devices) {
        my $out;
        $out = _get_smart_output( $device, '-a' );
        confess "Smartctl couldn't poll device $device\nSmartctl Output:\n$out\n"
          if ( !$out || $out !~ /START OF INFORMATION SECTION/ );

        chomp($out);
        $self->{'devices'}->{$device}->{'SMART_OUTPUT'} = $out;

        $self->_process_disk_attributes($device);
        $self->_process_disk_errors($device);
        $self->_process_disk_health($device);
        $self->_process_disk_model($device);
        $self->_process_disk_temp($device);
    }

    return;
}

sub _get_smart_output {
    my ( $device, $options ) = @_;
    $options = $options // '';

    die "smartctl binary was not found on your system, are you running as root?\n"
        if ( !defined $smartctl || !-f $smartctl );

    open my $fh, '-|', "$smartctl $device $options" or confess "Can't run smartctl binary\n";
    local $/ = undef;
    my $smart_output = <$fh>;

    if ( $smart_output =~ /Unknown USB bridge/ ) {
        open $fh, '-|', "$smartctl $device $options -d sat" or confess "Can't run smartctl binary\n";
        $smart_output = <$fh>;
    }
    return $smart_output;
}

sub _process_disk_attributes {
    my ( $self, $device ) = @_;
    $self->_validate_param($device);

    my $smart_output = $self->{'devices'}->{$device}->{'SMART_OUTPUT'};
    my ($smart_attributes) = $smart_output =~ /(ID# ATTRIBUTE_NAME.*)\nSMART Error/s;
    my @attributes = split /\n/, $smart_attributes;
    shift @attributes; #remove table header

    foreach my $attribute (@attributes) {
        my $id    = substr $attribute, 0,  +3;
        my $name  = substr $attribute, 4,  +24;
        my $value = substr $attribute, 83, +50;
        $id    = _trim($id);
        $name  = _trim($name);
        $value = _trim($value);
        $self->{'devices'}->{$device}->{'attributes'}->{$id} = [ $name, $value ];
    }

    return;



( run in 0.626 second using v1.01-cache-2.11-cpan-39bf76dae61 )