#!/usr/bin/perl -w # A little hard disk health report tool use strict; ### Settings #################################### # smartctl disk driver. "ata" for most SCSI, SATA and libata drives. my $driver = "ata"; # the disk to check. my $device = "/dev/sda"; # manufacturer-set limits (Here: HGST Travelstar 7K60) my %limits = ( load_unload => 300000, po_retract => 20000, po_cycles => 0, # no data in datasheet startstop_count => 300000, # no explicit data, but sounds like # it is the same as load_unload for # SAFE start/stops (no hard poweroff) poweron_hours => 20000, temp_min => 5, # °C temp_max => 55 # °C ); # your smartctl command line. my $smartctl = "sudo smartctl"; ################################################## # print disclaimer if ( ! defined $ARGV[0] || $ARGV[0] ne "-y" ) { print ' This script reports various values regarding the health of your hard drive. Use it at your own risk. to run it, edit the settings in the file and start it with "-y": '.$0.' -y '; exit(0); } # Values that are counted somehow. Everything but temperatures... my @counts = qw(load_unload po_retract po_cycles startstop_count poweron_hours); my %descriptions = ( load_unload => "Load/Unload cycles", po_retract => "Power-Off retract (Emergency unload?", po_cycles => "Power-On cycles", startstop_count => "Start/Stop (PM Spindown) count", poweron_hours => "Power-On hours", temp_min => "Minimum temperature", temp_max => "Maximum temperature"); my $attributes = `$smartctl -d $driver --attributes $device`; my %values; my $verbose = "no"; my @attributes; my $attr_section = "no"; foreach (split(/\n/, $attributes)) { chomp; if ($attr_section eq "yes") { my @attr = split(/\s+/); if ($attr[0] !~ /[0-9]+/) { shift @attr; } # remove leading spaces if ($verbose eq "yes") { foreach (@attr) { print "\"".$_. "\""."\t"; } print "\n"; } if ($attr[0] == 193) #Load/Unload { $values{load_unload} = $attr[9]; } elsif ($attr[0] == 192) #Poweroff Retract (emergency unload?) { $values{po_retract} = $attr[9]; } elsif ($attr[0] == 12) # Power Cycle count { $values{po_cycles} = $attr[9]; } elsif ($attr[0] == 4) # Start-Stop cycles { $values{startstop_count} = $attr[9]; } elsif ($attr[0] == 9) # Power Cycle count { $values{poweron_hours} = $attr[9]; } elsif ($attr[0] == 194) # Temperature { if ($attr[12] =~ /([0-9]+)\/([0-9]+)\).*/) { $values{temp_min} = $1; $values{temp_max} = $2; } } } if ($_ =~ /.*ATTRIBUTE_NAME.*/) { # start parsing after table headers. $attr_section = "yes"; } } print "PM-related Hard disk health:\n\n"; foreach (@counts) { printf("%40s : %s\n", $descriptions{$_}, $values{$_}. ($limits{$_} > 0 ? " of ".$limits{$_}." (".sprintf("%3.2f",( $values{$_}/$limits{$_} * 100.0))."% of life)" : "")); } printf("%40s : %s\n", "Temperatures during lifetime", $values{temp_min}." to ".$values{temp_max}.", manufacturer limits: ". $limits{temp_min}." to ".$limits{temp_max}." (°C)"); printf("%40s : %2.3f\n", "Average Load/Unload cycles per hour", $values{load_unload} / $values{poweron_hours}); print "\n";