forked from Spearfoot/FreeNAS-scripts
-
Notifications
You must be signed in to change notification settings - Fork 0
/
smart_report.sh
152 lines (131 loc) · 5.5 KB
/
smart_report.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#!/bin/sh
### Parameters ###
# Specify your email address here:
email=""
freenashost=$(hostname -s | tr '[:lower:]' '[:upper:]')
smartctl=/usr/local/sbin/smartctl
logfile="/tmp/smart_report.tmp"
subject="SMART Status Report for ${freenashost}"
tempWarn=40
tempCrit=45
sectorsCrit=10
testAgeWarn=1
warnSymbol="?"
critSymbol="!"
# We need a list of the SMART-enabled drives on the system. Choose one of these
# three methods to provide the list. Comment out the two unused sections of code.
# 1. A string constant; just key in the devices you want to report on here:
#drives="da1 da2 da3 da4 da5 da6 da7 da8 ada0"
# 2. A systcl-based technique suggested on the FreeNAS forum:
#drives=$(for drive in $(sysctl -n kern.disks); do \
#if [ "$("${smartctl}" -i /dev/${drive} | grep "SMART support is: Enabled" | awk '{print $3}')" ]
#then printf ${drive}" "; fi done | awk '{for (i=NF; i!=0 ; i--) print $i }')
# 3. A smartctl-based function:
get_smart_drives()
{
gs_drives=$("${smartctl}" --scan | grep "dev" | awk '{print $1}' | sed -e 's/\/dev\///' | tr '\n' ' ')
gs_smartdrives=""
for gs_drive in $gs_drives; do
gs_smart_flag=$("${smartctl}" -i /dev/"$gs_drive" | grep "SMART support is: Enabled" | awk '{print $4}')
if [ "$gs_smart_flag" = "Enabled" ]; then
gs_smartdrives=$gs_smartdrives" "${gs_drive}
fi
done
eval "$1=\$gs_smartdrives"
}
drives=""
get_smart_drives drives
# end of method 3.
### Set email headers ###
(
echo "To: ${email}"
echo "Subject: ${subject}"
echo "Content-Type: text/html"
echo "MIME-Version: 1.0"
printf "\r\n"
) > ${logfile}
### Set email body ###
echo "<pre style=\"font-size:14px\">" >> ${logfile}
###### summary ######
(
echo "########## SMART status report summary for all drives on server ${freenashost} ##########"
echo ""
echo "+------+------------------+----+-----+-----+-----+-------+-------+--------+------+----------+------+-------+----+"
echo "|Device|Serial |Temp|Power|Start|Spin |ReAlloc|Current|Offline |Seek |Total |High |Command|Last|"
echo "| |Number | |On |Stop |Retry|Sectors|Pending|Uncorrec|Errors|Seeks |Fly |Timeout|Test|"
echo "| | | |Hours|Count|Count| |Sectors|Sectors | | |Writes|Count |Age |"
echo "+------+------------------+----+-----+-----+-----+-------+-------+--------+------+----------+------+-------+----+"
) >> ${logfile}
for drive in $drives; do
(
lastTestHours=$("${smartctl}" -l selftest /dev/"${drive}" | grep "# 1" | awk '{print $9}')
"${smartctl}" -A -i -v 7,hex48 /dev/"${drive}" | \
awk -v device=${drive} -v tempWarn=${tempWarn} -v tempCrit=${tempCrit} -v sectorsCrit=${sectorsCrit} \
-v testAgeWarn=${testAgeWarn} -v warnSymbol="${warnSymbol}" -v critSymbol=${critSymbol} \
-v lastTestHours="${lastTestHours}" '
/Serial Number:/{serial=$3}
/190 Airflow_Temperature/{temp=$10}
/194 Temperature/{temp=$10}
/Power_On_Hours/{split($10,a,"+");sub(/h/,"",a[1]);onHours=a[1];}
/Start_Stop_Count/{startStop=$10}
/Spin_Retry_Count/{spinRetry=$10}
/Reallocated_Sector/{reAlloc=$10}
/Current_Pending_Sector/{pending=$10}
/Offline_Uncorrectable/{offlineUnc=$10}
/Seek_Error_Rate/{seekErrors=("0x" substr($10,3,4));totalSeeks=("0x" substr($10,7))}
/High_Fly_Writes/{hiFlyWr=$10}
/Command_Timeout/{cmdTimeout=$10}
END {
testAge=sprintf("%.0f", (onHours - lastTestHours) / 24);
if (temp > tempCrit || reAlloc > sectorsCrit || pending > sectorsCrit || offlineUnc > sectorsCrit)
device=device " " critSymbol;
else if (temp > tempWarn || reAlloc > 0 || pending > 0 || offlineUnc > 0 || testAge > testAgeWarn)
device=device " " warnSymbol;
seekErrors=sprintf("%d", seekErrors);
totalSeeks=sprintf("%d", totalSeeks);
if (totalSeeks == "0") {
seekErrors="N/A";
totalSeeks="N/A";
}
if (hiFlyWr == "") hiFlyWr="N/A";
if (cmdTimeout == "") cmdTimeout="N/A";
printf "|%-6s|%-18s| %s |%5s|%5s|%5s|%7s|%7s|%8s|%6s|%10s|%6s|%7s|%4s|\n",
device, serial, temp, onHours, startStop, spinRetry, reAlloc, pending, offlineUnc,
seekErrors, totalSeeks, hiFlyWr, cmdTimeout, testAge;
}'
) >> ${logfile}
done
(
echo "+------+------------------+----+-----+-----+-----+-------+-------+--------+------+----------+------+-------+----+"
) >> ${logfile}
###### for each drive ######
for drive in $drives; do
brand=$("${smartctl}" -i /dev/"${drive}" | grep "Model Family" | awk '{print $3, $4, $5}')
if [ -z "$brand" ]; then
brand=$("${smartctl}" -i /dev/"${drive}" | grep "Device Model" | awk '{print $3, $4, $5}')
fi
serial=$("${smartctl}" -i /dev/"${drive}" | grep "Serial Number" | awk '{print $3}')
(
echo ""
echo "########## SMART status report for ${drive} drive (${brand}: ${serial}) ##########"
"${smartctl}" -n never -H -A -l error /dev/"${drive}"
"${smartctl}" -n never -l selftest /dev/"${drive}" | grep "# 1 \|Num" | cut -c6-
) >> ${logfile}
done
sed -i '' -e '/smartctl 6.*/d' ${logfile}
sed -i '' -e '/smartctl 5.*/d' ${logfile}
sed -i '' -e '/smartctl 4.*/d' ${logfile}
sed -i '' -e '/Copyright/d' ${logfile}
sed -i '' -e '/=== START OF READ/d' ${logfile}
sed -i '' -e '/SMART Attributes Data/d' ${logfile}
sed -i '' -e '/Vendor Specific SMART/d' ${logfile}
sed -i '' -e '/SMART Error Log Version/d' ${logfile}
echo "</pre>" >> ${logfile}
### Send report ###
if [ -z "${email}" ]; then
echo "No email address specified, information available in ${logfile}"
else
# sendmail -t < ${logfile}
sendmail ${email} < ${logfile}
rm ${logfile}
fi