Rev 153 | Rev 165 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
#!/usr/bin/env perl
use warnings;
use strict;
# Description: Use smartctl to get disk information
our $VERSION = '1.0';
# R. W. Rodolico
# grabs smart readings from all drives in system
# note that in the case of some hardware RAID controller, will list the components of a "drive" and the drive itself,
# so you may have up to twice the number of entries than you have physical drives, for example, if you have a megaraid
# controller where each physical drive is also a single logical drive.
BEGIN {
push @INC, shift;
}
use library;
exit 0 unless checkDate( 'w' ); # run this only on Mondays
sub trim {
my $value = shift;
$value =~ s/^\s+|\s+$//g;
return $value;
}
sub getSmartReport {
my ($drive, $type) = @_;
my @report = `smartctl -a $drive $type`;
chomp @report;
return @report;
}
sub getTotalWrites {
my @report = @_;
return -2 unless grep{ /(Solid State Device)|(SSD)/ } @report;
my @temp = grep{ /^Sector Size:/ } @report;
my $sectors = shift @temp;
# print "The Value is [$sectors]\n"; die;
if ( $sectors =~ m/^Sector Size\:\s+(\d+)\s+bytes/ ) {
$sectors = $1;
# print "Sectors is $sectors\n"; die;
@temp = grep{ /^241/ } @report;
my $lbas = $temp[0];
if ( $lbas =~ m/(\d+)\s*$/ ) {
$lbas = $1;
return $lbas * $sectors;
} else {
return -3;
}
} else {
return -4;
}
return -1; # we could not find something
}
sub getInformation {
my @report = @_;
my %info;
my %keys = (
'Model Family:' => {
'tag' => 'Make',
'regex' => '(.*)'
},
'Device Model:' => {
'tag' => 'Model',
'regex' => '(.*)'
},
'Serial number:' => {
'tag' => 'Serial',
'regex' => '(.*)'
},
'Serial Number:' => {
'tag' => 'Serial',
'regex' => '(.*)'
},
'User Capacity:' => {
'tag' => 'Capacity',
'regex' => '([0-9,]+)'
},
'Logical block size:' =>{
'tag' => 'Sector Size',
'regex' => '(\d+)'
},
'Sector Size:' => {
'tag' => 'Sector Size',
'regex' => '(\d+)'
},
'Rotation Rate:' => {
'tag' => 'Rotation',
'regex' => '(.*)'
}
);
foreach my $key ( keys %keys ) {
my @temp = grep { /^$key/ } @report;
if ( @temp ) {
$temp[0] =~ m/^$key\s+(.*)$/;
my $value = $1;
$value =~ m/$keys{$key}->{'regex'}/;
$info{$keys{$key}->{'tag'}} = $1;
}
}
# remove comma's from capacity
$info{'Capacity'} =~ s/,//g if $info{'Capacity'};
return \%info;
}
# category we will use for all values found
# see sysinfo for a list of valid categories
my $CATEGORY = 'attributes';
# run the commands necessary to do whatever you want to do
# The library entered above has some helper routines
# validCommandOnSystem -- passed a name, returns the fully qualified path or '' if it does not exist
# cleanUp - passed a delimiter and a string, does the following (delimiter can be '')
# chomps the string (removes trailing newlines)
# removes all text BEFORE the delimiter, the delimiter, and any whitespace
# thus, the string 'xxI Am x a weird string' with a newline will become
# 'a weird string' with no newline
# now, return the tab delimited output (to STDOUT). $CATEGORY is the first
# item, name as recognized by sysinfo is the second and the value is
# the last one. For multiple entries, place on separate lines (ie, newline separated)
# check for commands we want to run
my %commands = (
'smartctl' => '',
);
# check the commands for validity
foreach my $command ( keys %commands ) {
$commands{$command} = &validCommandOnSystem( $command );
}
# bail if we don't have the commands we need
exit 1 unless $commands{'smartctl'};
# Get all the drives on the system
my %allDrives = map { $_ =~ '(^[a-z0-9/]+)\s+(.*)\#'; ($1,$2) } `smartctl --scan`;
#foreach my $key ( keys %allDrives ) { print "$key\t$allDrives{$key}\n"; } die;
# output the drives and information as tab delimited,
foreach my $thisDrive ( sort keys %allDrives ) {
#print "$thisDrive\n";
print "$CATEGORY\t$thisDrive Type\t$allDrives{$thisDrive}\n";
my @report = &getSmartReport( $thisDrive, $allDrives{$thisDrive} );
#print join( "\n", @report ) . "\n"; die;
my $writes = &getTotalWrites( @report );
my $info = &getInformation( @report );
$info->{'writes'} = $writes if $writes > 0;
#print Dumper( $info );
foreach my $key ( keys %$info ) {
print "$CATEGORY\t$thisDrive $key\t" . $info->{$key} . "\n";
}
}
exit 0;