2020-02-27 13:33:19 +01:00
#!/bin/sh
# .. vim: foldmarker=[[[,]]]:foldmethod=marker
# This script will try to run a smart test on all compatible devices.
# The test can be passed as first argument.
# Vars [[[
debug = "0"
## Colors [[[
c_redb = '\033[1;31m'
c_magentab = '\033[1;35m'
c_reset = '\033[0m'
## ]]]
temp_dir = $( mktemp -d -t smart.run.test-XXXXXX.tmp)
smart_device_list = " ${ temp_dir } /smart.device.list "
# ]]]
2020-02-27 15:15:47 +01:00
# Functions
2020-02-27 15:50:51 +01:00
## Print help message [[[
print_help_message( ) {
cat << HELP
usage: $( basename " ${ 0 } " ) [ TEST TYPE]
Try to run a SMART test on all compatible devices.
positional arguments:
TEST TYPE Test type to run on all devices. Can be:
short ( default) - runs SMART Short Self Test ( usually under ten minutes)
long - runs SMART Extended Self Test ( tens of minutes to
several hours) .
EXAMPLE :
- Run a short test
$( basename " ${ 0 } " ) short
HELP
}
## ]]]
2020-02-27 15:58:06 +01:00
## Manage the arguments [[[
manage_arguments( ) {
2020-02-27 15:50:51 +01:00
_nb_arg = " ${# } "
_all_args = " ${ * } "
2020-02-27 15:58:06 +01:00
[ " ${ debug } " -eq "0" ] && printf " ${ c_magentab } %-6b ${ c_reset } \n " " DEBUG : manage_arguments func − ${ _nb_arg } argument(s) to manage. List:\n ${ _all_args } "
2020-02-27 15:50:51 +01:00
## If help is needed [[[
if printf -- '%s' " ${ _all_args } " | grep -q -E -- "-h|--help|help" ; then
print_help_message
exit 0
fi
## ]]]
2020-02-27 15:58:06 +01:00
# Manage arguments [[[
case " ${ _nb_arg } " in
0 )
## Set test to run to default (short)
test_to_run = "short"
; ;
1 )
test_to_run = " ${ 1 } "
; ;
* )
## More than managed number of arguments
print_help_message
exit 2
; ;
esac
# ]]]
2020-02-27 15:50:51 +01:00
}
## ]]]
2020-02-27 15:15:47 +01:00
## Test if a disk really support SMART [[[
## Smartctl can give an health status even without a full support
## of SMART for some type (eg. scsi or megaraid).
## Exemple : SMART support is: Unavailable - device lacks SMART capability.
is_disk_path_support_smart( ) {
_disk_path = " ${ 1 } "
_disk_type = " ${ 2 } "
_smarctl_support_result = " ${ temp_dir } /smart.support. $( basename " ${ _disk_path } " ) "
smart_support_msg = ""
[ " ${ debug } " -eq "0" ] && printf " ${ c_magentab } %-6b ${ c_reset } \n " " DEBUG : is_disk_path_support_smart func − check if SMART is supported on : ${ _disk_path } with ${ _disk_type } TYPE. "
## Create file
true > " ${ _smarctl_support_result } "
## Grep only "support" lines from disk's informations
smartctl -d " ${ _disk_type } " -i -- " ${ _disk_path } " | grep -E "^SMART support is:" -- >> " ${ _smarctl_support_result } "
## If the file is not empty
if test -s " ${ _smarctl_support_result } " ; then
## Parse all "support" lines
while IFS = read -r _line; do
### If a line doesn't contain enable or available
if ! printf -- '%s' " ${ _line } " | grep -q -E -- "(Enabled|Available)"
then
smart_support_msg = " ${ _line } "
[ " ${ debug } " -eq "0" ] && printf " ${ c_magentab } %-6b ${ c_reset } \n " " DEBUG : is_disk_path_support_smart func − SMART is not fully supported on : ${ _disk_path } with ${ _disk_type } TYPE. See smartctl informations :\n ${ smart_support_msg } "
fi
done < " ${ _smarctl_support_result } "
else
smart_support_msg = " ERROR : Enable to open ${ _disk_path } DEVICE with ${ _disk_type } TYPE. Be sure to have sufficient permission for this device. "
printf " ${ c_redb } %-6b ${ c_reset } \n " " ERROR : Enable to open ${ _disk_path } DEVICE with ${ _disk_type } TYPE. Be sure to have sufficient permission for this device. "
fi
}
## ]]]
## Test the type of disk with smartctl [[[
## Cause the scanned one might not be the one to use
choose_correct_type( ) {
_disk_path = " ${ 1 } "
_scanned_disk_type = " ${ 2 } "
_default_disk_type = "auto"
disk_type = ""
for _test_disk_type in " ${ _default_disk_type } " " ${ _scanned_disk_type } " ; do
is_disk_path_support_smart " ${ _disk_path } " " ${ _test_disk_type } "
## If no message, the type is correct
if [ -z " ${ smart_support_msg } " ] ; then
disk_type = " ${ _test_disk_type } "
[ " ${ debug } " -eq "0" ] && printf " ${ c_magentab } %-6b ${ c_reset } \n " " DEBUG : choose_correct_disk_type func − SMART seems fully supported on : ${ _disk_path } with ${ _test_disk_type } TYPE. "
return
fi
done
}
## ]]]
2020-02-27 15:58:06 +01:00
manage_arguments " ${ @ } "
2020-02-27 15:50:51 +01:00
2020-02-27 13:33:19 +01:00
# Create files
true > " ${ smart_device_list } "
# Get the list of all available devices
smartctl --scan >> " ${ smart_device_list } "
2020-02-27 14:01:18 +01:00
if test -s " ${ smart_device_list } " ; then
while IFS = read -r LINE; do
## Get device path
2020-02-27 15:15:47 +01:00
disk_path = $( echo " ${ LINE } " | cut -d" " -f1)
2020-02-27 14:01:18 +01:00
## Try to determine the best type
2020-02-27 15:15:47 +01:00
scanned_disk_type = $( echo " ${ LINE } " | cut -d" " -f3)
[ " ${ debug } " -eq "0" ] && printf " \n ${ c_magentab } %-6b ${ c_reset } \n " " DEBUG : smartctl scan ${ disk_path } with TYPE ${ scanned_disk_type } . "
choose_correct_type " ${ disk_path } " " ${ scanned_disk_type } "
## If no correct type was found for this device
if [ -z " ${ disk_type } " ] ; then
[ " ${ debug } " -eq "0" ] && printf " ${ c_magentab } %-6b ${ c_reset } \n " " DEBUG : SMART is not fully supported on ${ disk_path } . "
else
[ " ${ debug } " -eq "0" ] && printf " ${ c_magentab } %-6b ${ c_reset } \n " " DEBUG : for disk ${ disk_path } , now use TYPE ${ disk_type } . "
fi
2020-02-27 14:01:18 +01:00
done < " ${ smart_device_list } "
# If the file is empty
else
printf " ${ c_redb } %-6b ${ c_reset } \n " " ERROR : The device list looks empty, check ${ smart_device_list } file and \`smartctl --scan\` command. "
exit 1
fi
2020-02-27 13:33:19 +01:00
# Remove temp_dir if debug is disable
[ " ${ debug } " -eq "0" ] || rm -rf -- " ${ temp_dir } "
exit 0