R710-Fan-Control/hddtemp
Tim Connors 00413326be hddtemp, smart-intercept-spindown: handle idle, add --numeric, --no-device
Filter out temperature=255 at this stage rather than in clients who
use us

Allow hddtemp to output a simpler format if --no-device --numeric is
requested

Ignore idle disks as well in order not to bring them out of idle mode
and thus reset timer
2025-09-13 04:20:15 +10:00

93 lines
2.7 KiB
Perl
Executable file

#!/usr/bin/perl
# A replacement for the various stock versions of hddtemp that all
# seem to have big issues with different types of drives, or spin up
# drives that are in powersaving spun-down mode, etc.
# For those disks like some of my SAS drives where `smartctl
# --nocheck=standby` and `hdparm -C` actually spins up the disk,
# detect whether a disk is spun down with sdparm commands, and don't
# invoke smartctl if it is. Otherwise, some of our other disks like
# our 16TB SATA drives on Dell Perc controllers give unreliable status to `sdparm
# --command=sense`, but `smartctl --nocheck=standby` does seem to
# reliably detect their spundown state anyway, so we continue to
# supply `--nocheck=standby` to cover this case.
# Much of this stolen from /etc/munin/plugins/hddtemp_smartctl
use strict;
use warnings;
$ENV{PATH}="$ENV{PATH}:/usr/sbin:/sbin";
sub usage {
print STDERR "@_\n" if @_;
print STDERR "Usage: hddtemp [-n|--numeric] [--no-device] <devices>\n";
exit 1;
}
# FIXME: consider using megaclisas-status if it's available, although
# finding the mapping might be interesting...
my $units="°C";
my $print_device=1;
while (@ARGV and $ARGV[0] =~ /^-/) {
if ($ARGV[0] eq "--numeric" or $ARGV[0] eq "-n") {
shift @ARGV;
$units="";
} elsif ($ARGV[0] eq "--no-device") {
shift @ARGV;
$print_device=0;
} else {
usage;
}
}
usage "Supply device name(s)" if (!@ARGV);
my $last_exit=0;
foreach my $drive (@ARGV) {
my $output=`/usr/local/bin/smart-intercept-spindown -A -i $drive`;
$last_exit = $?>>8;
if (!($output =~ /(Standby|Idle) condition/)) {
my $model = "";
my $temp = "";
if ($output =~ /(Model Number|Device Model):\s*(.*)/) {
$model = "$2: ";
}
if ($output =~ /Current Drive Temperature:\s*(\d+)/) {
$temp = $1;
} elsif ($output =~ /^(194 Temperature_(Celsius|Internal).*)/m) {
my @F = split /\s+/, $1;
$temp = $F[9];
} elsif ($output =~ /^(231 Temperature_Celsius.*)/m) {
my @F = split ' ', $1;
$temp = $F[9];
} elsif ($output =~ /^(190 (Airflow_Temperature_Cel|Temperature_Case).*)/m) {
my @F = split ' ', $1;
$temp = $F[9];
} elsif ($output =~ /Temperature:\s*(\d+) Celsius/) {
$temp = $1;
} else {
print "$drive: SMART not available\n";
next;
}
# Some devices permanently return a *temperature* of 255, so
# ignore them too
if ($temp == 255) {
print "$drive: ${model}Temperature not available through SMART\n";
} else {
if ($print_device) {
print "$drive: $model$temp$units\n";
} else {
print "$temp$units\n";
}
}
} else {
print "$drive: Sleeping. Temperature not available\n";
};
}
exit $last_exit;