Rev 153 | 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
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 = shift;
my @report = `smartctl -a /dev/$drive`;
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' => '(.*)'
},
'User Capacity:' => {
'tag' => 'Capacity',
'regex' => '([0-9,]+)'
},
'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 = 'system';
# 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' => '',
'geom' => '',
'lsblk' => '',
);
# check the commands for validity
foreach my $command ( keys %commands ) {
$commands{$command} = &validCommandOnSystem( $command );
}
$commands{'getDrives'} = $commands{ 'lsblk' } ? $commands{'lsblk'} . " | grep disk | cut -d' ' -f1" :
( $commands{'geom'} ? $commands{'geom'} . " disk list | grep 'Geom name:' | cut -d':' -f 2" : '' );
# bail if we don't have the commands we need
exit 1 unless $commands{'getDrives'} and $commands{'smartctl'};
# Get all the drives on the system
my %allDrives = map { &trim($_) => 0 } `$commands{'getDrives'}`;
# output the drives and information as tab delimited,
foreach my $thisDrive ( sort keys %allDrives ) {
print "$thisDrive\n";
my @report = &getSmartReport( $thisDrive );
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;