Skip to content

Instantly share code, notes, and snippets.

@ddnomad
Last active October 29, 2020 16:36
Show Gist options
  • Save ddnomad/edfce9902cbf12736fc2ef59e2448a2c to your computer and use it in GitHub Desktop.
Save ddnomad/edfce9902cbf12736fc2ef59e2448a2c to your computer and use it in GitHub Desktop.
Ghetto script to get temperatures of ZFS pool on Solaris 11
#!/usr/bin/env bash
set -euo pipefail
readonly DISK_TEMP_RE='.*\s([0-9]+ \(Min/Max [0-9]+/[0-9]+\))'
readonly ZPOOL_RE='^\s+NAME\s+STATE\s+.*$\n\s+(\w+)\s+ONLINE.*$\n.*\n(^\s+(\w+)\s+ONLINE.*$\n)+^$'
readonly SMARTCTL_CMD=/opt/csw/sbin/smartctl
readonly TABLE_FORMAT='%-10s %-20s %-8s %-25s\n'
readonly HIGH_TEMP_THRESH=41
readonly CRIT_TEMP_THRESH=50
function main {
# Build an index of pool name to disk name mappings
local pools_info
pools_info="$(zpool status -v | pcregrep -M "${ZPOOL_RE}")"
local pools_map
declare -A pools_map
local next_line_pool_name
local in_pool_list_block
local pool_name
local pool_disks
next_line_pool_name=false
in_pool_list_block=false
pool_name=
pool_disks=
while read -r line; do
if test "${line:-stab}" = stab && test -n "${pool_disks}"; then
pools_map["${pool_name}"]="${pool_disks}"
in_pool_list_block=false
pool_name=
pool_disks=
elif [[ "${line}" == NAME* ]]; then
next_line_pool_name=true
elif test "${next_line_pool_name}" = true; then
pool_name="$(cut -f1 -d' ' <<< "${line}")"
in_pool_list_block=true
next_line_pool_name=false
elif test "${in_pool_list_block}" = true; then
if [[ "${line}" == *-* ]]; then
continue
fi
pool_disks="${pool_disks} $(cut -f1 -d' ' <<< "${line}")"
fi
done <<< "$(tr -s ' ' <<< ${pools_info})"
# Add the last pool data to the map
pools_map["${pool_name}"]="${pool_disks}"
# Get temperature readings from each disk sensor and print them out (including
# information about which zpool this disk is a part of)
local smartctl_info
smartctl_info="$("${SMARTCTL_CMD}" --scan)"
# Output a table header
printf "${TABLE_FORMAT}" \
'DISK' 'TEMP (Celsius)' 'POOL' 'PATH'
while IFS= read -rd '' pool_name; do
local disks
read -a disks <<< "${pools_map["${pool_name}"]}"
for disk in "${disks[@]}"; do
local disk_path
disk_path="$(grep "${disk}" <<< "${smartctl_info}" | cut -f1 -d' ')"
local disk_info
disk_info="$(sudo "${SMARTCTL_CMD}" -a "${disk_path}")" || {
tput setaf 3
echo "(!!!) Disk may be damaged: ${disk_path}"
echo "(!!!) Run these commands to get details:"
echo " * sudo zpool status -v ${pool_name}"
echo " * sudo ${SMARTCTL_CMD} -a ${disk_path}"
tput sgr0
}
local disk_temp
disk_temp="$(\
grep 'Temperature_Celsius' <<< "${disk_info}" | \
gsed -nE "s@${DISK_TEMP_RE}@\1@p")"
# Determine whether temperature is too hot
local disk_temp_int
disk_temp_int="$(cut -f1 -d' ' <<< ${disk_temp})"
if test "${disk_temp_int}" -ge "${CRIT_TEMP_THRESH}"; then
tput bold
tput setaf 1
elif test "${disk_temp_int}" -ge "${HIGH_TEMP_THRESH}"; then
tput setaf 3
fi
# Output table row
printf "${TABLE_FORMAT}" \
"${disk}" "${disk_temp}" "${pool_name}" "${disk_path}"
tput sgr0
done
done < <(printf '%s\0' "${!pools_map[@]}" | gsort -z)
}
main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment