#!/usr/bin/env bash
# Beschreibung: Überwacht die S.M.A.R.T Werte eines physikalischen Devices und gibt diese als XML in PRTG aus
# Parameter: /dev/sda
# Autor: Patrick Asmus
# Web: https://www.techniverse.net
# Version: 1.1
# Datum: 28.03.2025
# Modifikation: Grenzwerte hinzugefuegt
#####################################################
DEVICE="$1"
if [ -z "$DEVICE" ]; then
echo "1Kein Gerät angegeben"
exit 1
fi
if ! command -v smartctl &>/dev/null; then
echo "1smartctl nicht installiert"
exit 1
fi
if [ ! -b "$DEVICE" ]; then
echo "1Gerät $DEVICE nicht gefunden"
exit 1
fi
SMART_OUTPUT=$(sudo smartctl -x "$DEVICE")
# Herstellerinformationen extrahieren
MODEL=$(echo "$SMART_OUTPUT" | awk -F: '/Model Number|Device Model/ {print $2}' | xargs)
SERIAL=$(echo "$SMART_OUTPUT" | awk -F: '/Serial Number/ {print $2}' | xargs)
VENDOR=$(echo "$SMART_OUTPUT" | awk -F: '/Vendor/ {print $2}' | xargs)
[ -z "$VENDOR" ] && VENDOR=$(echo "$MODEL" | awk '{print $1}')
MODEL=${MODEL:-Unbekanntes Modell}
SERIAL=${SERIAL:-Keine Seriennummer}
VENDOR=${VENDOR:-Unbekannter Hersteller}
# Gerätetyp erkennen
if echo "$SMART_OUTPUT" | grep -q "NVMe Version"; then
TYPE="nvme"
else
TYPE="sata"
fi
XML=""
if [ "$TYPE" = "sata" ]; then
get_value() {
echo "$SMART_OUTPUT" | awk -v id="$1" '$1 == id {print $10}'
}
TEMP=$(get_value 194)
HOURS=$(get_value 9)
REALLOC=$(get_value 5)
REALLOC_EVENT=$(get_value 196)
PENDING=$(get_value 197)
UNCORRECTABLE=$(get_value 198)
CRC_ERROR=$(get_value 199)
REPORTED_UNCORRECT=$(get_value 187)
for var in TEMP HOURS REALLOC REALLOC_EVENT PENDING UNCORRECTABLE CRC_ERROR REPORTED_UNCORRECT; do
eval "[ -z \$$var ] && $var=0"
done
XML+="
Temperature (°C)$TEMPTemperature14555
Power-On Hours$HOURSHours
Reallocated Sectors$REALLOCCount110
Reallocated Events$REALLOC_EVENTCount
Pending Sectors$PENDINGCount11
Offline Uncorrectable$UNCORRECTABLECount11
Reported Uncorrect$REPORTED_UNCORRECTCount
CRC Error Count$CRC_ERRORCount
$VENDOR | $MODEL | SN: $SERIAL | $DEVICE"
elif [ "$TYPE" = "nvme" ]; then
get_nvme_value() {
echo "$SMART_OUTPUT" | grep -E "^$1:" | head -n1 | awk -F: '{gsub(/^[ \t]+|[ \t]+$/, "", $2); print $2}'
}
TEMP=$(get_nvme_value "Temperature" | awk '{print $1}')
HOURS=$(get_nvme_value "Power On Hours" | sed 's/\.//g')
PERCENT_USED=$(get_nvme_value "Percentage Used" | sed 's/%//')
MEDIA_ERRORS=$(get_nvme_value "Media and Data Integrity Errors")
ERROR_LOGS=$(get_nvme_value "Error Information Log Entries")
UNSAFE_SHUTDOWNS=$(get_nvme_value "Unsafe Shutdowns")
WARN_TEMP_TIME=$(get_nvme_value "Warning Comp. Temperature Time")
CRIT_TEMP_TIME=$(get_nvme_value "Critical Comp. Temperature Time")
POWER_CYCLES=$(get_nvme_value "Power Cycles")
WRITTEN_TB=$(get_nvme_value "Data Units Written" | grep -o '\[[0-9.]* TB\]' | tr -d '[]TB ')
READ_TB=$(get_nvme_value "Data Units Read" | grep -o '\[[0-9.]* TB\]' | tr -d '[]TB ')
# === Wear Level Verlauf verfolgen ===
CACHE_FILE="/var/prtg/scriptsxml/.smart_wear_${DEVICE//\//_}.cache"
NOW_DATE=$(date '+%Y-%m-%d')
if [ -f "$CACHE_FILE" ]; then
LAST_LEVEL=$(awk -F: '{print $1}' "$CACHE_FILE")
LAST_DATE=$(awk -F: '{print $2}' "$CACHE_FILE")
DIFF=$((PERCENT_USED - LAST_LEVEL))
if [ "$DIFF" -ne 0 ]; then
TREND=" – +$DIFF % seit $LAST_DATE"
echo "$PERCENT_USED:$NOW_DATE" > "$CACHE_FILE"
else
TREND=" – unverändert seit $LAST_DATE"
fi
else
echo "$PERCENT_USED:$NOW_DATE" > "$CACHE_FILE"
TREND=" – erster Messpunkt"
fi
for var in TEMP HOURS PERCENT_USED MEDIA_ERRORS ERROR_LOGS UNSAFE_SHUTDOWNS WARN_TEMP_TIME CRIT_TEMP_TIME POWER_CYCLES WRITTEN_TB READ_TB; do
eval "[ -z \$$var ] && $var=0"
done
XML+="
Temperature (°C)$TEMPTemperature16580
Power-On Hours$HOURSHours
Wear Level (Percentage Used)$PERCENT_USEDPercent17090
Power Cycles$POWER_CYCLESCount
Media/Data Errors$MEDIA_ERRORSCount11
SMART Error Logs$ERROR_LOGSCount11050
Unsafe Shutdowns$UNSAFE_SHUTDOWNSCount
Warning Temp Time$WARN_TEMP_TIMETimeSeconds
Critical Temp Time$CRIT_TEMP_TIMETimeSeconds110
Data Written (TB)$WRITTEN_TBCustom
Data Read (TB)$READ_TBCustom
$VENDOR | $MODEL | SN: $SERIAL | $DEVICE | Wear: $PERCENT_USED %$TREND"
else
XML+="1Unbekannter Gerätetyp"
fi
XML+=""
echo "$XML"