119 lines
3.1 KiB
Perl
119 lines
3.1 KiB
Perl
#!/usr/bin/perl
|
|
|
|
use strict;
|
|
use warnings;
|
|
use JSON;
|
|
use Getopt::Long;
|
|
use File::Which;
|
|
|
|
my $dev = undef;
|
|
my $type = 'auto';
|
|
my $what = 'json';
|
|
my $pretty = 0;
|
|
|
|
GetOptions(
|
|
'device=s' => \$dev,
|
|
'type=s' => \$type,
|
|
'what=s' => \$what,
|
|
'pretty' => \$pretty
|
|
);
|
|
|
|
if (not defined $dev or $dev !~ m|^/dev/\w+(/\w+)*$|){
|
|
print "Invalid --device\n";
|
|
exit 1;
|
|
} elsif ($what !~ m/^\w+$/){
|
|
print "Invalid --what\n";
|
|
exit 1;
|
|
} elsif ($type !~ m/^\w+\+*\w+(,\w+)*$/){
|
|
print "Invalid --type\n";
|
|
exit 1;
|
|
}
|
|
|
|
my $json = {
|
|
temperature_celsius => 25,
|
|
power_on_hours => 0,
|
|
power_cycle_count => 0,
|
|
reallocated_sector_count => 0,
|
|
current_pending_sector => 0,
|
|
offline_uncorrectable => 0,
|
|
percent_lifetime_remain => 100,
|
|
firmware_version => 0
|
|
};
|
|
my $smartctl = which('smartctl');
|
|
|
|
sub print_out {
|
|
if ($what eq 'json'){
|
|
print to_json($json, { pretty => $pretty });
|
|
exit 0;
|
|
} elsif (defined $json->{$what}){
|
|
print $json->{$what} . "\n";
|
|
exit 0;
|
|
} else {
|
|
print "ZBX_NOTSUPPORTED\n";
|
|
exit 1;
|
|
}
|
|
}
|
|
|
|
sub get_smart_attr {
|
|
my $smart = shift;
|
|
my $attr = shift;
|
|
|
|
if (defined $smart->{ata_smart_attributes}->{table}){
|
|
foreach (@{$smart->{ata_smart_attributes}->{table}}){
|
|
if ($_->{name} eq $attr){
|
|
return $_;
|
|
}
|
|
}
|
|
}
|
|
return undef;
|
|
}
|
|
|
|
if (not defined $smartctl){
|
|
$what = 'error';
|
|
print_out();
|
|
}
|
|
|
|
my $data = from_json(qx($smartctl -a $dev -d $type --json=c));
|
|
|
|
if (defined $data->{temperature}->{current}){
|
|
$json->{temperature_celsius} = $data->{temperature}->{current};
|
|
}
|
|
|
|
if (defined $data->{power_on_time}->{hours}){
|
|
$json->{power_on_hours} = $data->{power_on_time}->{hours};
|
|
}
|
|
|
|
if (defined $data->{power_cycle_count}){
|
|
$json->{power_cycle_count} = $data->{power_cycle_count};
|
|
}
|
|
|
|
if (defined $data->{firmware_version}){
|
|
$json->{firmware_version} = $data->{firmware_version};
|
|
}
|
|
|
|
my ($pending, $realloc, $offline, $remain);
|
|
if ($pending = get_smart_attr($data, 'Current_Pending_Sector')){
|
|
$json->{current_pending_sector} = $pending->{raw}->{value};
|
|
}
|
|
|
|
if ($realloc = get_smart_attr($data, 'Reallocated_Sector_Ct') || get_smart_attr($data, 'Reallocated_Event_Count')){
|
|
$json->{reallocated_sector_count} = $realloc->{raw}->{value};
|
|
} elsif (defined $data->{nvme_smart_health_information_log}->{media_errors}){
|
|
# NMVe can report media error, so report it as reallocated sectors
|
|
$json->{reallocated_sector_count} = $data->{nvme_smart_health_information_log}->{media_errors};
|
|
}
|
|
|
|
if ($offline = get_smart_attr($data, 'Offline_Uncorrectable')){
|
|
$json->{offline_uncorrectable} = $offline->{raw}->{value};
|
|
}
|
|
|
|
if ($remain = get_smart_attr($data, 'Percent_Lifetime_Remain')){
|
|
$json->{percent_lifetime_remain} = $remain->{value};
|
|
} elsif ($remain = get_smart_attr($data, 'Wear_Leveling_Count')) {
|
|
$json->{percent_lifetime_remain} = $remain->{value};
|
|
} elsif (defined $data->{nvme_smart_health_information_log}->{percentage_used}){
|
|
# NMVe sometime report the estimated life used, instead of the remaining
|
|
$json->{percent_lifetime_remain} = 100 - $data->{nvme_smart_health_information_log}->{percentage_used};
|
|
}
|
|
print_out();
|