#!/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 # 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}}"); }