@ -31,13 +31,22 @@
#
#
# Maybe also edit the other disk compatibility DB in synoboot, used during boot time.
# Maybe also edit the other disk compatibility DB in synoboot, used during boot time.
# It's also parsed and checked and probably in some cases it could be more critical to patch that one instead.
# It's also parsed and checked and probably in some cases it could be more critical to patch that one instead.
#
# Change SAS drive firmware version detection to use smartctl to support SAS drives that hdparm doesn't work with.
# DONE
# DONE
# Make DSM recheck disk compatability so reboot not needed (DSM 7 only).
# Added support for M.2 SATA drives.
#
# Can now skip processing M.2 drives by running script with the -m2 flag.
#
# Changed method of getting drive and firmware version so script is faster and easier to maintain.
# - No longer using smartctl or hdparm.
#
# Changed SAS drive firmware version detection to support SAS drives that hdparm doesn't work with.
#
#
# Fixed DSM6 bug when DSM6 used the old db file format.
# Removed error message and aborting if *.db.new not found (clean DSM installs don't have a *.db.new).
#
# Force DSM to check disk compatibility so reboot not needed (DSM 6 may still need a reboot).
#
# Fixed DSM 6 issue when DSM 6 has the old db file format.
#
#
# Add support for SAS drives.
# Add support for SAS drives.
#
#
@ -52,7 +61,7 @@
# Optionally disable "support_disk_compatibility".
# Optionally disable "support_disk_compatibility".
scriptver = "1.1.10 "
scriptver = "1.1.11 "
# Check latest release with GitHub API
# Check latest release with GitHub API
get_latest_release( ) {
get_latest_release( ) {
@ -75,19 +84,21 @@ fi
# Check for flags with getopts
# Check for flags with getopts
OPTERR = 0
OPTERR = 0
while getopts "sfn" option; do
while getopts "sfnm " option; do
# Need to ensure any other long flags do not contain s, n, or f
# Need to ensure any other long flags do not contain s, n, or f
if [ [ ! ${# option } -gt "1" ] ] ; then
if [ [ ! ${# option } -gt "1" ] ] ; then
case ${ option ,,, } in
case ${ option ,,, } in
s)
s)
showedits = yes
showedits = yes
#echo showedits # debug
; ;
; ;
n)
n)
nodbupdate = yes # For future use
nodbupdate = yes # For future use
; ;
; ;
m)
m2 = no # Don't add M.2 drives to db files
; ;
f)
f)
force = yes
force = yes # Disable "support_disk_compatibility"
; ;
; ;
*)
*)
; ;
; ;
@ -112,96 +123,85 @@ fi
# Check script is running as root
# Check script is running as root
if [ [ $( whoami ) != "root" ] ] ; then
if [ [ $( whoami ) != "root" ] ] ; then
echo -e "\e[41m ERROR \e[0m This script must be run as root or sudo!"
echo -e "\e[41mERROR\e[0m This script must be run as root or sudo!"
exit 1
exit 1
fi
fi
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# Get list of installed SATA, SAS and NVMe drives
# Get list of installed SATA, SAS and M.2 NVMe/SATA drives
getModel( ) {
#for d in $(ls /sys/block); do
hdmodel = $( smartctl -i " $1 " | grep -i "Device Model:" | awk '{print $3 $4 $5}' )
for d in /sys/block/*; do
if [ [ ! $hdmodel ] ] ; then
# if [ ! -e /dev/"$d" ]; then
hdmodel = $( smartctl -i " $1 " | grep -i "Product:" | awk '{print $2 $3 $4}' )
# echo "Found /dev/$d" # debug
fi
# continue;
#echo "Model: $hdmodel" # debug
# fi
#echo $d # debug
# Brands that return "BRAND <model>" and need "BRAND " removed.
case " $( basename -- " ${ d } " ) " in
# Smartmontools database in /var/lib/smartmontools/drivedb.db
sd*| hd*)
hdmodel = ${ hdmodel # "WDC " } # Remove "WDC " from start of model name
if [ [ $d = ~ [ hs] d[ a-z] $ ] ] ; then
hdmodel = ${ hdmodel # "HGST " } # Remove "HGST " from start of model name
hdmodel = $( cat " $d /device/model " )
hdmodel = ${ hdmodel # "TOSHIBA " } # Remove "TOSHIBA " from start of model name
hdmodel = $( printf "%s" " $hdmodel " | xargs) # trim leading and trailing white space
#echo "Model: '$hdmodel'" # debug
# Old drive brands
hdmodel = ${ hdmodel # "Hitachi " } # Remove "Hitachi " from start of model name
hdmodel = ${ hdmodel # "SAMSUNG " } # Remove "SAMSUNG " from start of model name
hdmodel = ${ hdmodel # "FUJISTU " } # Remove "FUJISTU " from start of model name
hdmodel = ${ hdmodel # "APPLE HDD " } # Remove "APPLE HDD " from start of model name
shopt -s extglob
hdmodel = ${ hdmodel /#*([[ : space : ]]) } # Remove leading spaces
hdmodel = ${ hdmodel /%*([[ : space : ]]) } # Remove trailing spaces
shopt -u extglob
#echo "Model: $hdmodel" # debug
}
getFwVersion( ) {
tmp = $( hdparm -i " $1 " | grep Model)
fwrev = $( printf %s " $tmp " | cut -d"," -f 2 | cut -d"=" -f 2)
#echo "Firmware: $fwrev" # debug
}
getNVMeModel( ) {
nvmemodel = $( cat " $1 " /model)
shopt -s extglob
nvmemodel = ${ nvmemodel /#*([[ : space : ]]) } # Remove leading spaces
nvmemodel = ${ nvmemodel /%*([[ : space : ]]) } # Remove trailing spaces
shopt -u extglob
#echo "NVMe Model: $nvmemodel" # debug
}
getNVMeFwVersion( ) {
nvmefw = $( cat " $1 " /firmware_rev)
nvmefw = $( echo " $nvmefw " | xargs) # trim leading and trailing white space
#echo "NVMe Firmware: $nvmefw" # debug
}
fwrev = $( cat " $d /device/rev " )
fwrev = $( printf "%s" " $fwrev " | xargs) # trim leading and trailing white space
#echo "Firmware: '$fwrev'" # debug
for d in $( cat /proc/partitions | awk '{print $4}' ) ; do
if [ ! -e /dev/" $d " ] ; then
continue ;
fi
#echo $d # debug
case " $d " in
hd*| sd*)
if [ [ $d = ~ [ hs] d[ a-z] { 1,2} $ ] ] ; then
#echo -e "\n$d" # debug
getModel " /dev/ $d "
getFwVersion " /dev/ $d "
if [ [ $hdmodel ] ] && [ [ $fwrev ] ] ; then
if [ [ $hdmodel ] ] && [ [ $fwrev ] ] ; then
hdparm += ( " ${ hdmodel } , ${ fwrev } " )
hdlist += ( " ${ hdmodel } , ${ fwrev } " )
fi
fi
fi
fi
; ;
; ;
sas*| sata *)
sata*| sas*)
if [ [ $d = ~ ( sas| sata) [ 0-9] [ 0-9] ?[ 0-9] ?$ ] ] ; then
if [ [ $d = ~ ( sas| sata) [ 0-9] [ 0-9] ?[ 0-9] ?$ ] ] ; then
#echo -e "\n$d" # debug
hdmodel = $( cat " $d /device/model " )
getModel " /dev/ $d "
hdmodel = $( printf "%s" " $hdmodel " | xargs) # trim leading and trailing white space
getFwVersion " /dev/ $d "
#echo "Model: '$hdmodel'" # debug
fwrev = $( cat " $d /device/rev " )
fwrev = $( printf "%s" " $fwrev " | xargs) # trim leading and trailing white space
#echo "Firmware: '$fwrev'" # debug
if [ [ $hdmodel ] ] && [ [ $fwrev ] ] ; then
if [ [ $hdmodel ] ] && [ [ $fwrev ] ] ; then
hdparm += ( " ${ hdmodel } , ${ fwrev } " )
hdlist += ( " ${ hdmodel } , ${ fwrev } " )
fi
fi
fi
fi
; ;
; ;
nvme*)
nvme*)
if [ [ $d = ~ nvme[ 0-9] [ 0-9] ?n[ 0-9] [ 0-9] ?$ ] ] ; then
if [ [ $d = ~ nvme[ 0-9] [ 0-9] ?n[ 0-9] [ 0-9] ?$ ] ] ; then
#echo -e "\n$d" # debug
if [ [ $m2 != "no" ] ] ; then
n = n$( printf "%s" " $d " | cut -d "n" -f 2)
nvmemodel = $( cat " $d /device/model " )
getNVMeModel " /sys/class/nvme/ $n "
nvmemodel = $( printf "%s" " $nvmemodel " | xargs) # trim leading and trailing white space
getNVMeFwVersion " /sys/class/nvme/ $n "
#echo "NVMe Model: '$nvmemodel'" # debug
if [ [ $nvmemodel ] ] && [ [ $nvmefw ] ] ; then
nvmelist += ( " ${ nvmemodel } , ${ nvmefw } " )
nvmefw = $( cat " $d /device/firmware_rev " )
nvmefw = $( printf "%s" " $nvmefw " | xargs) # trim leading and trailing white space
#echo "NVMe Firmware: '$nvmefw'" # debug
if [ [ $nvmemodel ] ] && [ [ $nvmefw ] ] ; then
nvmelist += ( " ${ nvmemodel } , ${ nvmefw } " )
fi
fi
fi
; ;
nvc*) # M.2 SATA drives (in PCIe card only?)
#if [[ $d =~ nvc[0-9][0-9]?p[0-9][0-9]?$ ]]; then
if [ [ $d = ~ nvc[ 0-9] [ 0-9] ?$ ] ] ; then
if [ [ $m2 != "no" ] ] ; then
nvmemodel = $( cat " $d /device/model " )
nvmemodel = $( printf "%s" " $nvmemodel " | xargs) # trim leading and trailing white space
#echo "M.2 SATA Model: '$nvmemodel'" # debug
#nvmefw=$(cat "$d/device/firmware_rev")
nvmefw = $( cat " $d /device/rev " )
nvmefw = $( printf "%s" " $nvmefw " | xargs) # trim leading and trailing white space
#echo "M.2 SATA Firmware: '$nvmefw'" # debug
if [ [ $nvmemodel ] ] && [ [ $nvmefw ] ] ; then
nvmelist += ( " ${ nvmemodel } , ${ nvmefw } " )
fi
fi
fi
fi
fi
; ;
; ;
@ -209,16 +209,16 @@ for d in $(cat /proc/partitions | awk '{print $4}'); do
done
done
# Sort hdparm array into new hdds array to remove duplicates
# Sort hdlist array into new hdds array to remove duplicates
if [ [ ${# hdparm [@] } -gt "0" ] ] ; then
if [ [ ${# hdlist [@] } -gt "0" ] ] ; then
while IFS = read -r -d '' x; do
while IFS = read -r -d '' x; do
hdds += ( " $x " )
hdds += ( " $x " )
done < <( printf "%s\0" " ${ hdparm [@] } " | sort -uz)
done < <( printf "%s\0" " ${ hdlist [@] } " | sort -uz)
fi
fi
# Check hdds array isn't empty
# Check hdds array isn't empty
if [ [ ${# hdds [@] } -eq "0" ] ] ; then
if [ [ ${# hdds [@] } -eq "0" ] ] ; then
echo -e "\e[41m ERROR \e[0m No drives found!" && exit 2
echo -e "\e[41mERROR\e[0m No drives found!" && exit 2
else
else
echo " HDD/SSD models found: ${# hdds [@] } "
echo " HDD/SSD models found: ${# hdds [@] } "
num = "0"
num = "0"
@ -239,9 +239,11 @@ fi
# Check nvmes array isn't empty
# Check nvmes array isn't empty
if [ [ ${# nvmes [@] } -eq "0" ] ] ; then
if [ [ ${# nvmes [@] } -eq "0" ] ] ; then
echo -e "No NVMe drives found\n"
if [ [ $m2 != "no" ] ] ; then
echo -e "No M.2 drives found\n"
fi
else
else
echo " NVMe drive models found: ${# nvmes [@] } "
echo " M.2 drive models found: ${# nvmes [@] } "
num = "0"
num = "0"
while [ [ $num -lt " ${# nvmes [@] } " ] ] ; do
while [ [ $num -lt " ${# nvmes [@] } " ] ] ; do
echo " ${ nvmes [num] } "
echo " ${ nvmes [num] } "
@ -257,20 +259,20 @@ fi
db1 = " /var/lib/disk-compatibility/ ${ model } _host ${ version } .db "
db1 = " /var/lib/disk-compatibility/ ${ model } _host ${ version } .db "
db2 = " /var/lib/disk-compatibility/ ${ model } _host ${ version } .db.new "
db2 = " /var/lib/disk-compatibility/ ${ model } _host ${ version } .db.new "
if [ [ ! -f " $db1 " ] ] ; then echo -e " \e[41m ERROR \e[0m $db1 not found! " && exit 3; fi
if [ [ ! -f " $db1 " ] ] ; then echo -e " \e[41mERROR\e[0m $db1 not found! " && exit 3; fi
#if [[ ! -f "$db2" ]]; then echo -e "\e[41m ERROR \e[0m $db2 not found!" && exit 4; fi
#if [[ ! -f "$db2" ]]; then echo -e "\e[41mERROR\e[0m $db2 not found!" && exit 4; fi
# new installs don't have a .new file
# new installs don't have a .db. new file
# Detect drive db type
# Detect drive db type
if grep -F '{"disk_compatbility_info":' " $db1 " >/dev/null; then
if grep -F '{"disk_compatbility_info":' " $db1 " >/dev/null; then
# DSM7 drive db files start with {"disk_compatbility_info":
# DSM 7 drive db files start with {"disk_compatbility_info":
dbtype = 7
dbtype = 7
elif grep -F '{"success":1,"list":[' " $db1 " >/dev/null; then
elif grep -F '{"success":1,"list":[' " $db1 " >/dev/null; then
# DSM7 drive db files start with {"success":1,"list":[
# DSM 6 drive db files start with {"success":1,"list":[
dbtype = 6
dbtype = 6
else
else
echo -e " \e[41m ERROR \e[0m Unknown database type $( basename -- " ${ db1 } " ) ! "
echo -e " \e[41mERROR\e[0m Unknown database type $( basename -- " ${ db1 } " ) ! "
exit 7
exit 7
fi
fi
#echo "dbtype: $dbtype" # debug
#echo "dbtype: $dbtype" # debug
@ -281,7 +283,7 @@ if [[ ! -f "$db1.bak" ]]; then
if cp " $db1 " " $db1 .bak " ; then
if cp " $db1 " " $db1 .bak " ; then
echo -e " Backed up database to $( basename -- " ${ db1 } " ) .bak\n "
echo -e " Backed up database to $( basename -- " ${ db1 } " ) .bak\n "
else
else
echo -e " \e[41m ERROR \e[0m Failed to backup $( basename -- " ${ db1 } " ) ! "
echo -e " \e[41mERROR\e[0m Failed to backup $( basename -- " ${ db1 } " ) ! "
exit 5
exit 5
fi
fi
fi
fi
@ -294,8 +296,8 @@ Red='\e[0;31m'
Off = $'\e[0m'
Off = $'\e[0m'
function updatedb( ) {
function updatedb( ) {
hdmodel = $( printf %s " $1 " | cut -d"," -f 1)
hdmodel = $( printf " %s" " $1 " | cut -d"," -f 1)
fwrev = $( printf %s " $1 " | cut -d"," -f 2)
fwrev = $( printf " %s" " $1 " | cut -d"," -f 2)
#echo arg1 "$1" # debug
#echo arg1 "$1" # debug
#echo arg2 "$2" # debug
#echo arg2 "$2" # debug
@ -324,13 +326,15 @@ function updatedb() {
db2Edits = $(( db2Edits + 1 ))
db2Edits = $(( db2Edits + 1 ))
fi
fi
else
else
echo -e " \n\e[41m ERROR \e[0m Failed to update v7 $( basename -- " $2 " ) ${ Off } "
echo -e " \n\e[41mERROR\e[0m Failed to update v7 $( basename -- " $2 " ) ${ Off } "
exit 6
exit 6
fi
fi
else
else
# example:
# example:
# {"model":"WD60EFRX-68MYMN1","firmware":"82.00A82","rec_intvl":[1]},
# {"model":"WD60EFRX-68MYMN1","firmware":"82.00A82","rec_intvl":[1]},
string = " {\"model\":\" ${ hdmodel } \",\"firmware\":\" ${ fwrev } \",\"rec_intvl\":\[1\]}, "
# Don't need to add firmware version?
#string="{\"model\":\"${hdmodel}\",\"firmware\":\"${fwrev}\",\"rec_intvl\":\[1\]},"
string = " {\"model\":\" ${ hdmodel } \",\"firmware\":\"\",\"rec_intvl\":\[1\]}, "
# {"success":1,"list":[
# {"success":1,"list":[
startstring = "{\"success\":1,\"list\":\["
startstring = "{\"success\":1,\"list\":\["
@ -348,7 +352,7 @@ function updatedb() {
db2Edits = $(( db2Edits + 1 ))
db2Edits = $(( db2Edits + 1 ))
fi
fi
else
else
echo -e " \n\e[41m ERROR \e[0m Failed to update $( basename -- " $2 " ) ${ Off } "
echo -e " \n\e[41mERROR\e[0m Failed to update $( basename -- " $2 " ) ${ Off } "
exit 8
exit 8
fi
fi
fi
fi
@ -365,7 +369,7 @@ while [[ $num -lt "${#hdds[@]}" ]]; do
num = $(( num + 1 ))
num = $(( num + 1 ))
done
done
# NVMe drives
# M.2 NVMe/SATA drives
num = "0"
num = "0"
while [ [ $num -lt " ${# nvmes [@] } " ] ] ; do
while [ [ $num -lt " ${# nvmes [@] } " ] ] ; do
updatedb " ${ nvmes [ $num ] } " " $db1 "
updatedb " ${ nvmes [ $num ] } " " $db1 "
@ -409,7 +413,7 @@ fi
if cp " $file " " $file .bak " ; then
if cp " $file " " $file .bak " ; then
echo " Backed up synoinfo.conf to $( basename -- " ${ file } " ) .bak "
echo " Backed up synoinfo.conf to $( basename -- " ${ file } " ) .bak "
else
else
echo -e " \e[41m ERROR \e[0m Failed to backup $( basename -- " ${ file } " ) ! "
echo -e " \e[41mERROR\e[0m Failed to backup $( basename -- " ${ file } " ) ! "
exit 6
exit 6
fi
fi
fi
fi
@ -430,7 +434,7 @@ fi
if [ [ $url = = "127.0.0.1" ] ] ; then
if [ [ $url = = "127.0.0.1" ] ] ; then
echo "Disabled drive db auto updates."
echo "Disabled drive db auto updates."
else
else
echo -e "\e[41m ERROR \e[0m Failed to disable drive db auto updates!"
echo -e "\e[41mERROR\e[0m Failed to disable drive db auto updates!"
fi
fi
fi
fi
fi
fi
@ -445,8 +449,7 @@ if [[ ${showedits,,} == "yes" ]]; then
if [ [ $db1Edits -gt "0" ] ] ; then
if [ [ $db1Edits -gt "0" ] ] ; then
echo -e " \nChanges to ${ Cyan } $( basename -- " $db1 " ) ${ Off } "
echo -e " \nChanges to ${ Cyan } $( basename -- " $db1 " ) ${ Off } "
jq . " $db1 " | tail -n " $lines "
jq . " $db1 " | tail -n " $lines "
fi
elif [ [ $db2Edits -gt "0" ] ] ; then
if [ [ $db2Edits -gt "0" ] ] ; then
echo -e " \nChanges to ${ Cyan } $( basename -- " $db2 " ) ${ Off } "
echo -e " \nChanges to ${ Cyan } $( basename -- " $db2 " ) ${ Off } "
jq . " $db2 " | tail -n " $lines "
jq . " $db2 " | tail -n " $lines "
fi
fi
@ -456,8 +459,7 @@ if [[ ${showedits,,} == "yes" ]]; then
if [ [ $db1Edits -gt "0" ] ] ; then
if [ [ $db1Edits -gt "0" ] ] ; then
echo -e " \nChanges to ${ Cyan } $( basename -- " $db1 " ) ${ Off } "
echo -e " \nChanges to ${ Cyan } $( basename -- " $db1 " ) ${ Off } "
jq . " $db1 " | head -n " $lines "
jq . " $db1 " | head -n " $lines "
fi
elif [ [ $db2Edits -gt "0" ] ] ; then
if [ [ $db2Edits -gt "0" ] ] ; then
echo -e " \nChanges to ${ Cyan } $( basename -- " $db2 " ) ${ Off } "
echo -e " \nChanges to ${ Cyan } $( basename -- " $db2 " ) ${ Off } "
jq . " $db2 " | head -n " $lines "
jq . " $db2 " | head -n " $lines "
fi
fi
@ -465,7 +467,7 @@ if [[ ${showedits,,} == "yes" ]]; then
fi
fi
# Make Synology check disk compata bility
# Make Synology check disk compati bility
/usr/syno/sbin/synostgdisk --check-all-disks-compatibility
/usr/syno/sbin/synostgdisk --check-all-disks-compatibility
status = $?
status = $?
if [ [ $status -eq "0" ] ] ; then
if [ [ $status -eq "0" ] ] ; then