Last active
October 29, 2020 16:36
-
-
Save ddnomad/edfce9902cbf12736fc2ef59e2448a2c to your computer and use it in GitHub Desktop.
Ghetto script to get temperatures of ZFS pool on Solaris 11
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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