Skip to content

Instantly share code, notes, and snippets.

@akorn
Last active February 25, 2022 20:20
Show Gist options
  • Save akorn/64beb47d0f134556b8cde04e44e41fa8 to your computer and use it in GitHub Desktop.
Save akorn/64beb47d0f134556b8cde04e44e41fa8 to your computer and use it in GitHub Desktop.
Query the status of all local SATA/SAS hard drives and summarize in a table; also for disks on hpsa controllers
#!/bin/zsh
#
# Copyright (C) 2016, 2022 András Korn. Licensed under the GPL v3.
#
# Purpose: query the status of all local SATA hard drives and summarize in a table.
#
# Not complete, but good enough for my own purposes. Patches welcome.
typeset -A diskattrs
typeset -A diskargs
typeset -A hpraid_sg # e.g. hpraid_sg[0]=/dev/sg42 means that ctrl 0 is at /dev/sg42
[[ -e /etc/default/list-disk-status ]] && . /etc/default/list-disk-status
# configuration takes the following form:
#
#diskargs[/dev/sdd]="-d cciss,0 /dev/sg0"
#diskargs[/dev/sde]="-d cciss,1 /dev/sg0"
#
# this means to query /dev/sg0 with '-d cciss,0' instead of /dev/sdd, but
# record the attributes obtained as if they were /dev/sdd's.
# this bit tries to guess the diskargs if none have been configured:
# make sure we have a fixed number of fields; cut out the bits that can contain spaces:
lsscsi -g | cut -c 1-30,54- | tr -d '][' | tr : ' ' | grep 'storage *HP' | while read ctrlnum crap crap disknum type brand devnode sgnode; do
hpraid_sg[$ctrlnum]=$sgnode
found_hpraid=1
done
if [[ $found_hpraid = 1 ]]; then
# note: lsscsi sometimes prints the wrong device node for hpraid attached disks, which will confuse this script
lsscsi -g | cut -c 1-30,54- | tr -d '][' | tr : ' ' | while read ctrlnum crap crap disknum type brand devnode sgnode; do
if [[ $type = disk ]] && [[ -n $hpraid_sg[$ctrlnum] ]]; then # this disk is on a hpraid controller
[[ -z "$diskargs[$devnode]" ]] && diskargs[$devnode]="-d cciss,$disknum $hpraid_sg[$ctrlnum]" # && echo 'diskargs['$devnode'] set to '"'-d cciss,$disknum $hpraid_sg[$ctrlnum]'"
fi
done
fi
# get_smart_attrib attrname disk
function get_attrib() {
echo -n "${diskattrs[${2}_${1}]:-n/a} "
}
function get_all_attribs() {
{
for disk in /dev/sd? /dev/sd[a-z][a-z](N); do
{
smartctl -i --attributes -f brief ${=diskargs[$disk]:-$disk} \
| sed -rn "
/^[[:space:]]*[0-9]/{
s/^[[:space:]]*[0-9]*[[:space:]]*/${disk//\//\\/}_/
s/^([^[:space:]]+)[[:space:]]+[^[:space:]]+[[:space:]]+[^[:space:]]+[[:space:]]+[^[:space:]]+[[:space:]]+[^[:space:]]+[[:space:]]+[^[:space:]]+[[:space:]]+([^[:space:]]+)$/\\1 \\2/p
}
/^Device [Mm]odel:/{
s/^[^:]*:[[:space:]]*//
s/ /_/g
s/^/${disk//\//\\/}_model /p
}
/^Serial [Nn]umber:/{
s/^[^:]*:[[:space:]]*//
s/^/${disk//\//\\/}_serial /p
}
/^LU WWN Device Id:/{
s/^[^:]*:[[:space:]]*//
s/ //g
s/^/${disk//\//\\/}_wwn 0x/p
}
/^Firmware [Vv]ersion:/{
s/^[^:]*:[[:space:]]*//
s/ /_/g
s/^/${disk//\//\\/}_fwversion /p
}
/^User [Cc]apacity:/{
s/^[^:]*:[[:space:]]*//
s/.*\\[//
s/\\].*//
s/ //g
s/^/${disk//\//\\/}_capacity /p
}
/^Sector [Ss]izes:.* bytes logical, .* bytes physical/{
s/^[^:]*:[[:space:]]*//
s/([0-9]*) bytes logical, ([0-9]*) bytes physical/${disk//\//\\/}_logicalsector \\1\\n${disk//\//\\/}_physicalsector \\2/p
}
/^Sector [Ss]ize:.* bytes logical\/physical/{
s/^[^:]*:[[:space:]]*//
s@([0-9]*) bytes logical/physical@${disk//\//\\/}_logicalsector \\1\n${disk//\//\\/}_physicalsector \\1@p
}
/^Rotation [Rr]ate:/{
s/^[^:]*:[[:space:]]*//
s/Solid State Device/SSD/
s/ //g
s/^/${disk//\//\\/}_rpm /p
}
"
} &
done
wait
} | while read disk_attr val; do
diskattrs[${disk_attr}]="$val"
done
lsscsi | fgrep /dev | while read line; do
disk="$line[54,$]"
scsiid="${line[1,13]/ */}"
disktype="${line[14,21]/ */}"
bus="${line[22,30]/ */}"
diskattrs[${disk}_scsiid]="$scsiid"
diskattrs[${disk}_disktype]="$disktype"
diskattrs[${disk}_bus]="$bus"
done
}
get_all_attribs
{
if ((found_hpraid)); then
echo "[scsi_id] type bus model fw devnode(*) serial cap rpm pend uncorr realloc lsz psz wwn args"
else
echo "[scsi_id] type bus model fw devnode serial cap rpm pend uncorr realloc lsz psz wwn args"
fi
for disk in /dev/sd? /dev/sd[a-z][a-z](N); do
get_attrib scsiid $disk
get_attrib disktype $disk
get_attrib bus $disk
get_attrib model $disk
get_attrib fwversion $disk
echo -n "$disk "
get_attrib serial $disk
get_attrib capacity $disk
get_attrib rpm $disk
get_attrib Current_Pending_Sector $disk
get_attrib Offline_Uncorrectable $disk
get_attrib Reallocated_Sector_Ct $disk
get_attrib logicalsector $disk
get_attrib physicalsector $disk
get_attrib wwn $disk
echo -n "$diskargs[$disk]"
echo
done
} | column -t
((found_hpraid)) && echo "NOTE: devnode detection is based on lsscsi output and unreliable if RAID controllers are used. Most of the rest of the information comes from smartctl (using 'args') and should be reliable."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment