parent
a819e4b860
commit
544fa567fd
@ -0,0 +1,78 @@
|
||||
#!/usr/bin/perl
|
||||
use warnings;
|
||||
use strict;
|
||||
use Term::ANSIColor;
|
||||
|
||||
my %temp = ('warn' => 38, 'bad' => 42);
|
||||
my %color = ('good' => 'green', 'warn' => 'yellow', 'bad' => 'red');
|
||||
my $devdir='/dev';
|
||||
my $smartctl='/usr/sbin/smartctl';
|
||||
my $infinity=clean(`/usr/bin/echo \xE2\x88\x9E`);
|
||||
my @udisks = ();
|
||||
my @disks = ();
|
||||
|
||||
# Needs to be manually updated
|
||||
my %disklocs = ('HKT01QJ2'=>'Bay 2 Slot 1',
|
||||
'HKT01QJP'=>'Bay 2 Slot 2',
|
||||
'S2TVNX0K402024'=>'Bay 2 Slot 3',
|
||||
'S2TVNX0K400456'=>'Bay 2 Slot 4',
|
||||
'S2TVNX0K402163'=>'Bay 2 Slot 5',
|
||||
'S2TVNX0K301389'=>'Bay 2 Slot 6',
|
||||
'ZR53ZB2F'=>'Bay 1 Slot 1',
|
||||
'3GJY8UKG'=>'Bay 1 Slot 2',
|
||||
'ZR58XJCF'=>'Bay 1 Slot 3',
|
||||
'3FGBP6VV'=>'Bay 1 Slot 4',
|
||||
'ZR58LSCD'=>'Bay 1 Slot 5');
|
||||
|
||||
opendir my($DH), $devdir or die $!;
|
||||
my @devicelist=readdir $DH;
|
||||
closedir $DH;
|
||||
|
||||
for(@devicelist) {
|
||||
my $device =$_;
|
||||
# Directory listing includes . and .. but these aren't disks!
|
||||
if ($device eq "." or $device eq "..") {next;}
|
||||
# We don't' care about partitions
|
||||
if ($device =~ /sd[a-z][0-9]/) {next;}
|
||||
if ($device =~ /sd[a-z]/) {
|
||||
push(@udisks,$device);
|
||||
}
|
||||
}
|
||||
|
||||
@disks=sort(@udisks);
|
||||
|
||||
printf("\n%-9s %-13s %-6s %-15s %-5s %-5s %-10s %-10s\n","Disk","Runtime","Pwr On","Serial","Temp","Max","Speed","Location");
|
||||
printf("%-18s\n","---------+------------+------+---------------+-----+-----+----------+----------");
|
||||
|
||||
# https://stackoverflow.com/a/5047362
|
||||
sub clean {my $text = shift; $text=~s/\n//g; $text=~s/\r//g;return $text;}
|
||||
|
||||
for (@disks) {
|
||||
my %diskdata=("disk_name"=>"/dev/$_");
|
||||
# https://www.unix.com/shell-programming-and-scripting/133687-perl-looping-through-output-system-command.html
|
||||
open my $cmd, '-|', "$smartctl -x $diskdata{'disk_name'}";
|
||||
while (my $line = <$cmd>) {
|
||||
# EX: Page Offset Size Value Flags Description
|
||||
# 0x01 0x010 4 37496 --- Power-on Hours
|
||||
# <explicit>x2 \s+ \d+ \s+ (\d+) [\s\-a-zA-Z0-9]+
|
||||
if ($line =~ /0x05\s+0x008\s+\d+\s+(\d+)/) {$diskdata{"current_temp"}=int($1);}
|
||||
elsif ($line =~ /0x05\s+0x058\s+\d+\s+(\d+)/) {$diskdata{"maximum_temp"}=int($1);}
|
||||
elsif ($line =~ /0x01\s+0x010\s+\d+\s+(\d+)/) {$diskdata{"power_hours"}=int($1);}
|
||||
elsif ($line =~ /0x01\s+0x008\s+\d+\s+(\d+)/) {$diskdata{"power_cycles"}=int($1);}
|
||||
#elsif ($line =~ /0x05\s+0x058\s+\d+\s+(\d+)/) {$diskdata{"maximum_temp"}=int($1);}
|
||||
elsif ($line =~ /Serial Number:\s+([a-zA-Z0-9]+)/) {$diskdata{"serial"}="$1";}
|
||||
elsif ($line =~ /Rotation Rate:\s+(Solid State Device|\d+\s*rpm)/) {
|
||||
if ($line =~ /.*:\s+(\d+\s+rpm)/) {$diskdata{"rotation_rate"}="$1";}
|
||||
else {$diskdata{"rotation_rate"}="SSD";}
|
||||
#else {$diskdata{"rotation_rate"}="$infinity rpm ";} # Unicode is a pain in the butt to align
|
||||
}
|
||||
}
|
||||
close $cmd;
|
||||
my $cstr="";
|
||||
if ($diskdata{"current_temp"} > $temp{"bad"}) {$cstr=colored($diskdata{"current_temp"}, $color{"bad"});}
|
||||
elsif($diskdata{"current_temp"} > $temp{"warn"}) {$cstr=colored($diskdata{"current_temp"}, $color{"warn"});}
|
||||
else {$cstr=colored($diskdata{"current_temp"}, $color{"good"});}
|
||||
# |---- padded due to color being interpreted as printable characters
|
||||
# dev ser tmp V max rot loc
|
||||
printf("%-9s %-13s %-6s %-15s %-5s %-5s %-10s %-10s\n","$diskdata{'disk_name'}","$diskdata{power_hours} hours","$diskdata{power_cycles}","$diskdata{serial}",clean($cstr),clean("$diskdata{'maximum_temp'}"),clean("$diskdata{'rotation_rate'}"), "$disklocs{$diskdata{serial}}");
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
#!/usr/bin/perl
|
||||
use warnings;
|
||||
use strict;
|
||||
use Term::ANSIColor;
|
||||
use Getopt::Long;
|
||||
use Time::localtime;
|
||||
|
||||
my %temp = ('warn' => 38, 'bad' => 42);
|
||||
my %color = ('good' => 'green', 'warn' => 'yellow', 'bad' => 'red');
|
||||
my $devdir='/dev';
|
||||
my $smartctl='/usr/sbin/smartctl';
|
||||
my @udisks = ();
|
||||
my @disks = ();
|
||||
my %rotobois=();
|
||||
my $CLEAR_LINE=`tput cub 40;tput el`;
|
||||
|
||||
|
||||
# https://stackoverflow.com/a/5047362
|
||||
sub clean {my $text = shift; $text=~s/\n//g; $text=~s/\r//g;return $text;}
|
||||
sub ptime {my $min = localtime->min < 10 ? "0".localtime->min : localtime->min;
|
||||
my $hr = localtime->hour < 10 ? "0".localtime->hour : localtime->hour;
|
||||
return "$hr:$min";}
|
||||
# https://www.perl.com/article/37/2013/8/18/Catch-and-Handle-Signals-in-Perl/
|
||||
$SIG{INT} = sub {printf("%s",$CLEAR_LINE);printf("\n%s\n\n",clean(colored("Caught ctrl+c - exiting",'red')));exit 0;};
|
||||
|
||||
opendir my($DH), $devdir or die $!;
|
||||
my @devicelist=readdir $DH;
|
||||
closedir $DH;
|
||||
|
||||
for(@devicelist) {
|
||||
my $device =$_;
|
||||
# Directory listing includes . and .. but these aren't disks!
|
||||
if ($device eq "." or $device eq "..") {next;}
|
||||
# We don't' care about partitions
|
||||
if ($device =~ /sd[a-z][0-9]/) {next;}
|
||||
if ($device =~ /sd[a-z]/) {
|
||||
push(@udisks,$device);
|
||||
}
|
||||
}
|
||||
|
||||
@disks=sort(@udisks);
|
||||
GetOptions("interval|i=i" => \( my $INTERVAL=300 ),"header|h=i" => \( my $HEADER_REPEAT = 24 ),) or die "command line arguments error";
|
||||
#my $INTERVAL=300;
|
||||
#my $HEADER_REPEAT=24;
|
||||
printf("\n%s\n","Running script forever, press ctrl+c to exit.\nScript args:");
|
||||
printf("%s\n%s\n\n","- Interval: $INTERVAL seconds","- Re-Header: $HEADER_REPEAT rows");
|
||||
|
||||
sub diskheader {
|
||||
my $rotoinv=keys %rotobois; if ($rotoinv > 0) {
|
||||
printf("%-10s", "24hr"); for (@disks) {printf("%-5s",$rotobois{"/dev/$_"});} printf("\n");}
|
||||
printf("%-10s", "Time"); for (@disks) {printf("%-5s",$_);} printf("\n");
|
||||
}
|
||||
sub headerlines {printf("%-10s", "---------+"); for (@disks) {printf("%-5s","----+");} printf("\n");}
|
||||
diskheader();
|
||||
headerlines();
|
||||
my $headertracker=0;
|
||||
while (1) {
|
||||
printf("%s",$CLEAR_LINE);
|
||||
if ($headertracker >= $HEADER_REPEAT) {$headertracker=0;headerlines();diskheader();headerlines();}
|
||||
printf("%5s%5s",ptime(),"");
|
||||
for (@disks) {
|
||||
my $diskname="/dev/$_";
|
||||
open my $cmd, '-|', "$smartctl -x $diskname";
|
||||
while (my $line = <$cmd>) {
|
||||
if ($line =~ /0x05\s+0x008\s+\d+\s+(\d+)/) {
|
||||
my $disktemp=int($1);
|
||||
if ($disktemp > $temp{"bad"}) {printf(" %-5s ",clean(colored($disktemp, $color{"bad"})));}
|
||||
elsif($disktemp > $temp{"warn"}) {printf(" %-5s ",clean(colored($disktemp, $color{"warn"})));}
|
||||
else {printf(" %-5s ",clean(colored($disktemp, $color{"good"})));}
|
||||
}
|
||||
elsif ($line =~ /Rotation Rate:\s+(Solid State Device|\d+\s*rpm)/) {
|
||||
if ($line =~ /.*:\s+(\d+)\s+rpm/) {$rotobois{"$diskname"}="$1";}
|
||||
else {$rotobois{"$diskname"}="SSD";}
|
||||
}
|
||||
}
|
||||
close $cmd;
|
||||
}
|
||||
printf("\n");
|
||||
printf("%s","Sleeping for $INTERVAL seconds...");
|
||||
$headertracker=$headertracker+1;
|
||||
select()->flush(); # Heccin buffered I/O gets caulk blocked by the sleep. This forces a flush to STDIO
|
||||
sleep($INTERVAL);
|
||||
}
|
Loading…
Reference in new issue