Created
May 25, 2025 08:14
-
-
Save hdavid0510/513c63fc12c5dd8b7888a2efd8976104 to your computer and use it in GitHub Desktop.
Get TBW of connected SSDs through smartctl
This file contains hidden or 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
#!/bin/bash | |
# ANSI colors | |
TEXT_CYAN='\e[96m' | |
TEXT_YELLOW='\e[93m' | |
TEXT_DEFAULT='\e[0m' | |
# Common formatter for byte-related outputs | |
function format_bytes_written_and_rate() { | |
local BYTES_WRITTEN=$1 | |
local POWER_ON_HOURS=$2 | |
local MB_WRITTEN=$(echo "scale=3; ${BYTES_WRITTEN} / 1048576" | bc) | |
local GB_WRITTEN=$(echo "scale=3; ${BYTES_WRITTEN} / 1073741824" | bc) | |
local TB_WRITTEN=$(echo "scale=3; ${BYTES_WRITTEN} / 1099511627776" | bc) | |
echo -e "${TEXT_YELLOW}Data written${TEXT_DEFAULT}" | |
printf "%20s MB\n" "$(echo ${MB_WRITTEN} | sed ':a;s/\B[0-9]\{3\}\>/,&/;ta')" | |
printf "%20s GB\n" "$(echo ${GB_WRITTEN} | sed ':a;s/\B[0-9]\{3\}\>/,&/;ta')" | |
printf "%20s TB\n" "$(echo ${TB_WRITTEN} | sed ':a;s/\B[0-9]\{3\}\>/,&/;ta')" | |
echo -e "${TEXT_YELLOW}Mean write rate${TEXT_DEFAULT}" | |
if [[ "${POWER_ON_HOURS}" =~ ^[0-9]+$ && "${POWER_ON_HOURS}" -ne 0 ]]; then | |
local MB_PER_HOUR=$(echo "scale=3; ${MB_WRITTEN} / ${POWER_ON_HOURS}" | bc) | |
printf "%20s MB/hr\n" "$(echo ${MB_PER_HOUR} | sed ':a;s/\B[0-9]\{3\}\>/,&/;ta')" | |
else | |
echo " N/A MB/hr" | |
fi | |
} | |
# Common function to print device info | |
function print_device_info() { | |
local DEVICE=$1 | |
echo -e "${TEXT_CYAN}" | |
fdisk -l "${DEVICE}" | grep -i "model" | |
echo -e -n "${TEXT_DEFAULT}" | |
fdisk -l "${DEVICE}" | grep "${DEVICE}" | |
} | |
function print_tbw_sata() { | |
local DEV=$1 | |
if [ -z "${DEV}" ]; then echo "No SATA SSD drive specified."; return 1; fi | |
if ! test -b "${DEV}"; then echo "Cannot find SATA SSD drive ${DEV}."; return 2; fi | |
local SMART_INFO=$(/usr/sbin/smartctl -A "${DEV}") | |
local POWER_ON_HOURS=$(echo "${SMART_INFO}" | grep "Power_On_Hours" | awk '{print $10}') | |
local WEAR_COUNT=$(echo "${SMART_INFO}" | grep "Wear_Leveling_Count" | awk '{print $4}' | sed 's/^0*//') | |
local LBAS_WRITTEN=$(echo "${SMART_INFO}" | grep "Total_LBAs_Written" | awk '{print $10}') | |
local BYTES_WRITTEN=$(echo "${LBAS_WRITTEN} * 512" | bc) | |
print_device_info "${DEV}" | |
echo -e "${TEXT_YELLOW}On time${TEXT_DEFAULT}" | |
printf "%20s hr\n" "$(echo ${POWER_ON_HOURS} | sed ':a;s/\B[0-9]\{3\}\>/,&/;ta')" | |
format_bytes_written_and_rate "${BYTES_WRITTEN}" "${POWER_ON_HOURS}" | |
echo -e "${TEXT_YELLOW}Drive health${TEXT_DEFAULT}" | |
if [[ "${WEAR_COUNT}" =~ ^[0-9]+$ ]]; then | |
printf "%20s WEAR_COUNT\n" "${WEAR_COUNT}" | |
else | |
echo " N/A WEAR_COUNT" | |
fi | |
echo "" | |
} | |
function print_tbw_nvme() { | |
local DEV=$1 | |
if [ -z "${DEV}" ]; then echo "No NVMe device specified."; return 1; fi | |
if ! test -b "${DEV}"; then echo "Cannot find NVMe device ${DEV}."; return 2; fi | |
local SMART_INFO=$(/usr/sbin/smartctl -x -d nvme "${DEV}") | |
local POWER_ON_HOURS=$(echo "${SMART_INFO}" | grep -i "Power On Hours" | awk -F: '{gsub(/ /, "", $2); gsub(/,/, "", $2); print $2}') | |
local DATA_UNITS_WRITTEN=$(echo "${SMART_INFO}" | grep -i "Data Units Written" | awk -F: '{gsub(/[^0-9]/, "", $2); print $2}') | |
local PERCENTAGE_USED=$(echo "${SMART_INFO}" | grep -i "Percentage Used" | awk -F: '{gsub(/[^0-9]/, "", $2); print $2}') | |
if [[ -z "${DATA_UNITS_WRITTEN}" || -z "${POWER_ON_HOURS}" ]]; then | |
echo "SMART data missing or unreadable for ${DEV}" | |
return 3 | |
fi | |
local BYTES_WRITTEN=$(echo "${DATA_UNITS_WRITTEN} * 512" | bc) | |
print_device_info "${DEV}" | |
echo -e "${TEXT_YELLOW}On time${TEXT_DEFAULT}" | |
printf " %20s hr\n" "$(echo ${POWER_ON_HOURS} | sed ':a;s/\B[0-9]\{3\}\>/,&/;ta')" | |
format_bytes_written_and_rate "${BYTES_WRITTEN}" "${POWER_ON_HOURS}" | |
echo -e "${TEXT_YELLOW}Drive health${TEXT_DEFAULT}" | |
if [[ "${PERCENTAGE_USED}" =~ ^[0-9]+$ ]]; then | |
printf "%20s %%\n" "$((100 - PERCENTAGE_USED))" | |
else | |
echo " N/A %" | |
fi | |
echo "" | |
} | |
# List of drives to check | |
for ssd in /dev/sd[a-z] /dev/nvme*n1; do | |
if [[ -b "$ssd" ]]; then | |
if [[ "$ssd" == /dev/nvme* ]]; then | |
print_tbw_nvme "$ssd" | |
else | |
print_tbw_sata "$ssd" | |
fi | |
fi | |
done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment