Update SMART's scripts.

Now define/use a list of drive known from smartmontools database and
compatible with selftest logging.
This commit is contained in:
Jeremy Gardais 2020-03-05 15:28:09 +01:00
parent 7eaac7e803
commit 250cb2709d
2 changed files with 57 additions and 19 deletions

View File

@ -17,6 +17,7 @@ use Data::Dumper;
my $bb = new Hobbit('smart'); my $bb = new Hobbit('smart');
my $temp_disk_list = "$ENV{'XYMONTMP'}/$ENV{'MACHINEDOTS'}.smart.drivedb.list";
my @disks = (); my @disks = ();
my %olderr = {}; my %olderr = {};
@ -25,13 +26,33 @@ my $CACHEFILE = "$ENV{'XYMONTMP'}/$ENV{'MACHINEDOTS'}.smart.cache";
&load_config("$ENV{'XYMONTMP'}/logfetch.$ENV{'MACHINEDOTS'}.cfg"); &load_config("$ENV{'XYMONTMP'}/logfetch.$ENV{'MACHINEDOTS'}.cfg");
my @disks_stat = stat($temp_disk_list);
my $disks_mtime = scalar @disks_stat ? $disks_stat[9] : 0;
#
# Regenerate disks list if the file is too old (600 minutes)
if (time() - $disks_mtime > 600)
{
unlink $temp_disk_list;
}
if (-e $temp_disk_list) {
# Should use the existing file
}
else {
# Create a file with the list of disks
system("ls -1 /dev/sd* | grep -vE '[0-9]' > $temp_disk_list") == 0
or die "system command to create $temp_disk_list failed: $?";
}
# fallback to disk detection if nothing defined in the config # fallback to disk detection if nothing defined in the config
unless (@disks) { unless (@disks) {
opendir(DIR, '/dev') or die $!; ## Put temp_disk_list content to disks array
while (my $dev = readdir(DIR)) { open(my $fh, '<:encoding(UTF-8)', $temp_disk_list)
push(@disks, "/dev/$dev") if ($dev =~ /^[vs]d.*\D$/); or die "Could not open file '$temp_disk_list' $!";
while (my $row = <$fh>) {
chomp $row;
push(@disks, "$row");
} }
closedir(DIR);
} }
my @stat = stat($CACHEFILE); my @stat = stat($CACHEFILE);

View File

@ -37,6 +37,13 @@ c_reset='\033[0m'
plugin_name=$(basename "${0}") plugin_name=$(basename "${0}")
plugin_result="${XYMONTMP}/${MACHINEDOTS}.smartoverall.plugin_result"
plugin_state="${XYMONTMP}/${MACHINEDOTS}.smartoverall.plugin_state"
device_list="${XYMONTMP}/${MACHINEDOTS}.smartoverall.dscan"
## List of devices known from the smartmontools base and compatible with test logging
## This file might be used by a more advanced script such as skazi0's one
drivedb_list="${XYMONTMP}/${MACHINEDOTS}.smart.drivedb.list"
# ]]] # ]]]
# Functions # Functions
@ -48,7 +55,7 @@ is_disk_support_smart() {
_disk="${1}" _disk="${1}"
_type="${2}" _type="${2}"
_smarctl_support_result="/tmp/dsupport.$(basename "${_disk}")" _smarctl_support_result="${XYMONTMP}/${MACHINEDOTS}.smartoverall.support.$(basename "${_disk}")"
smart_support_msg="" smart_support_msg=""
@ -79,7 +86,10 @@ is_disk_support_smart() {
[ "${debug}" -eq "0" ] && printf "${c_magentab}%-6b${c_reset}\n" "DEBUG: is_disk_support_smart func SMART is not fully supported on: ${_disk} with ${_type} type. See smartctl informations:\n${smart_support_msg}" [ "${debug}" -eq "0" ] && printf "${c_magentab}%-6b${c_reset}\n" "DEBUG: is_disk_support_smart func SMART is not fully supported on: ${_disk} with ${_type} type. See smartctl informations:\n${smart_support_msg}"
fi fi
rm -f -- "${_smarctl_support_result}" ## Clean temp files
### As the Xymon's tmpdir is used to store log files, no need to delete them at
### the end of the script. They will be emptied at the beginning of the next run.
} }
## ]]] ## ]]]
## Test the type of disk with smartctl [[[ ## Test the type of disk with smartctl [[[
@ -110,15 +120,16 @@ choose_correct_type() {
## ]]] ## ]]]
# Create or empty previous files # Create or empty previous files
true > /tmp/dres true > "${plugin_result}"
true > /tmp/dcheck true > "${plugin_state}"
true > /tmp/dscan true > "${device_list}"
true > "${drivedb_list}"
# Get the list of all available devices # Get the list of all available devices
smartctl --scan >> /tmp/dscan smartctl --scan >> "${device_list}"
# If the file is not empty # If the file is not empty
if test -s /tmp/dscan; then if test -s "${device_list}"; then
while IFS= read -r LINE; do while IFS= read -r LINE; do
## Get device path ## Get device path
DISK=$(echo "${LINE}" | cut -d" " -f1) DISK=$(echo "${LINE}" | cut -d" " -f1)
@ -165,6 +176,11 @@ https://www.smartmontools.org/wiki/FAQ#SmartmontoolsDatabase"
DSELFTEST_MSG="&clear Test logging are not supported:" DSELFTEST_MSG="&clear Test logging are not supported:"
else else
DSELFTEST_MSG="" DSELFTEST_MSG=""
### If the device is also known from smartmontools database
if printf -- '%s' "${DDRIVEDB_MSG}" | grep -q -E -- "green"
then
echo "${DISK}" >> "${drivedb_list}"
fi
fi fi
fi fi
@ -189,7 +205,7 @@ https://www.smartmontools.org/wiki/FAQ#SmartmontoolsDatabase"
fi fi
## Avoid duplicate device ## Avoid duplicate device
if ! grep -q "${DID}" /tmp/dres; then if ! grep -q "${DID}" "${plugin_result}"; then
## For summary ## For summary
echo "${COLOR} $DISK ${TYPE}" echo "${COLOR} $DISK ${TYPE}"
@ -205,29 +221,30 @@ https://www.smartmontools.org/wiki/FAQ#SmartmontoolsDatabase"
echo "------------------------------------------------------------" echo "------------------------------------------------------------"
echo "" echo ""
echo "" echo ""
} >> /tmp/dres } >> "${plugin_result}"
fi fi
done < /tmp/dscan >> /tmp/dcheck done < "${device_list}" >> "${plugin_state}"
# If the file is empty # If the file is empty
else else
echo "1&red Error while scanning devices with smartctl" >> /tmp/dcheck echo "1&red Error while scanning devices with smartctl" >> "${plugin_state}"
fi fi
# Set the global color according to the highest alert # Set the global color according to the highest alert
COLOR=$(< /tmp/dcheck awk '{print $1}' | sort | uniq | head -1 | cut -c3-) COLOR=$(< "${plugin_state}" awk '{print $1}' | sort | uniq | head -1 | cut -c3-)
# Send informations to Xymon server # Send informations to Xymon server
$XYMON "${XYMSRV}" "status ${MACHINE}.${plugin_name} ${COLOR} SMART health check $XYMON "${XYMSRV}" "status ${MACHINE}.${plugin_name} ${COLOR} SMART health check
$(< /tmp/dcheck cut -c2-) $(< "${plugin_state}" cut -c2-)
==================== Detailed status ==================== ==================== Detailed status ====================
$(cat /tmp/dres) $(cat "${plugin_result}")
" "
# Clean temp files # Clean temp files
rm -f -- /tmp/dres /tmp/dcheck /tmp/dscan ## As the Xymon's tmpdir is used to store log files, no need to delete them at
## the end of the script. They will be emptied at the beginning of the next run.
exit 0 exit 0