Skip to content

Commit 445f9c1

Browse files
Merge pull request #354 from prometheus/superq/smart_metrics
Add text file utility for SMART metrics
2 parents 481392d + 0d2314e commit 445f9c1

File tree

1 file changed

+139
-0
lines changed

1 file changed

+139
-0
lines changed
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
#!/bin/bash
2+
# Script informed by the collectd monitoring script for smartmontools (using smartctl)
3+
# by Samuel B. <samuel_._behan_(at)_dob_._sk> (c) 2012
4+
# source at: http://devel.dob.sk/collectd-scripts/
5+
6+
# TODO: This probably needs to be a little more complex. The raw numbers can have more
7+
# data in them than you'd think.
8+
# http://arstechnica.com/civis/viewtopic.php?p=22062211
9+
10+
disks="$(/usr/sbin/smartctl --scan | awk '{print $1 "|" $3}')"
11+
12+
parse_smartctl_attributes_awk="$(cat << 'SMARTCTLAWK'
13+
$1 ~ /^[0-9]+$/ && $2 ~ /^[a-zA-Z0-9_-]+$/ {
14+
gsub(/-/, "_");
15+
printf "%s_value{%s,smart_id=\"%s\"} %d\n", $2, labels, $1, $4
16+
printf "%s_worst{%s,smart_id=\"%s\"} %d\n", $2, labels, $1, $5
17+
printf "%s_threshold{%s,smart_id=\"%s\"} %d\n", $2, labels, $1, $6
18+
printf "%s_raw_value{%s,smart_id=\"%s\"} %d\n", $2, labels, $1, $10
19+
}
20+
SMARTCTLAWK
21+
)"
22+
23+
smartmon_attrs="$(cat << 'SMARTMONATTRS'
24+
airflow_temperature_cel
25+
command_timeout
26+
current_pending_sector
27+
end_to_end_error
28+
erase_fail_count
29+
g_sense_error_rate
30+
hardware_ecc_recovered
31+
host_reads_mib
32+
host_reads_32mib
33+
host_writes_mib
34+
host_writes_32mib
35+
load_cycle_count
36+
media_wearout_indicator
37+
nand_writes_1gib
38+
offline_uncorrectable
39+
power_cycle_count
40+
power_on_hours
41+
program_fail_count
42+
raw_read_error_rate
43+
reallocated_sector_ct
44+
reported_uncorrect
45+
sata_downshift_count
46+
spin_retry_count
47+
spin_up_time
48+
start_stop_count
49+
temperature_celsius
50+
total_lbas_read
51+
total_lbas_written
52+
udma_crc_error_count
53+
unsafe_shutdown_count
54+
workld_host_reads_perc
55+
workld_media_wear_indic
56+
workload_minutes
57+
SMARTMONATTRS
58+
)"
59+
smartmon_attrs="$(echo ${smartmon_attrs} | xargs | tr ' ' '|')"
60+
61+
parse_smartctl_attributes() {
62+
local disk="$1"
63+
local disk_type="$2"
64+
local labels="disk=\"${disk}\",type=\"${disk_type}\""
65+
local vars="$(echo "${smartmon_attrs}" | xargs | tr ' ' '|')"
66+
sed 's/^ \+//g' \
67+
| awk -v labels="${labels}" "${parse_smartctl_attributes_awk}" 2>/dev/null \
68+
| tr A-Z a-z \
69+
| grep -E "(${smartmon_attrs})"
70+
}
71+
72+
parse_smartctl_info() {
73+
local -i smart_available=0 smart_enabled=0
74+
local disk="$1" disk_type="$2"
75+
while read line ; do
76+
info_type="$(echo "${line}" | cut -f1 -d: | tr ' ' '_')"
77+
info_value="$(echo "${line}" | cut -f2- -d: | sed 's/^ \+//g')"
78+
case "${info_type}" in
79+
Model_Family) model_family="${info_value}" ;;
80+
Device_Model) device_model="${info_value}" ;;
81+
Serial_Number) serial_number="${info_value}" ;;
82+
Firmware_Version) fw_version="${info_value}" ;;
83+
Vendor) vendor="${info_value}" ;;
84+
Product) product="${info_value}" ;;
85+
Revision) revision="${info_value}" ;;
86+
Logical_Unit_id) lun_id="${info_value}" ;;
87+
esac
88+
if [[ "${info_type}" == 'SMART_support_is' ]] ; then
89+
case "${info_value:0:7}" in
90+
Enabled) smart_enabled=1 ;;
91+
Availab) smart_available=1 ;;
92+
Unavail) smart_available=0 ;;
93+
esac
94+
fi
95+
done
96+
if [[ -n "${model_family}" ]] ; then
97+
echo "device_info{disk=\"${disk}\",type=\"${disk_type}\",model_family=\"${model_family}\",device_model=\"${device_model}\",serial_number=\"${serial_number}\",firmware_version=\"${fw_version}\"} 1"
98+
elif [[ -n "${vendor}" ]] ; then
99+
echo "device_info{disk=\"${disk}\",type=\"${disk_type}\",vendor=\"${vendor}\",product=\"${product}\",revision=\"${revision}\",lun_id=\"${lun_id}\"} 1"
100+
fi
101+
echo "device_smart_available{disk=\"${disk}\",type=\"${disk_type}\"} ${smart_available}"
102+
echo "device_smart_enabled{disk=\"${disk}\",type=\"${disk_type}\"} ${smart_enabled}"
103+
}
104+
105+
output_format_awk="$(cat << 'OUTPUTAWK'
106+
BEGIN { v = "" }
107+
v != $1 {
108+
print "# HELP smartmon_" $1 " SMART metric " $1;
109+
print "# TYPE smartmon_" $1 " gauge";
110+
v = $1
111+
}
112+
{print "smartmon_" $0}
113+
OUTPUTAWK
114+
)"
115+
116+
format_output() {
117+
sort \
118+
| awk -F'{' "${output_format_awk}"
119+
}
120+
121+
smartctl_version="$(/usr/sbin/smartctl -V | head -n1 | awk '$1 == "smartctl" {print $2}')"
122+
123+
echo "smartctl_version{version=\"${smartctl_version}\"} 1" | format_output
124+
125+
if [[ "$(expr "${smartctl_version}" : '\([0-9]*\)\..*')" -lt 6 ]] ; then
126+
exit
127+
fi
128+
129+
device_list="$(/usr/sbin/smartctl --scan-open | awk '{print $1 "|" $3}')"
130+
131+
for device in ${device_list}; do
132+
disk="$(echo ${device} | cut -f1 -d'|')"
133+
type="$(echo ${device} | cut -f2 -d'|')"
134+
echo "smartctl_run{disk=\"${disk}\",type=\"${type}\"}" $(TZ=UTC date '+%s')
135+
# Get the SMART information
136+
/usr/sbin/smartctl -i -d "${type}" "${disk}" | parse_smartctl_info "${disk}" "${type}"
137+
# Get the SMART attributes
138+
/usr/sbin/smartctl -A -d "${type}" "${disk}" | parse_smartctl_attributes "${disk}" "${type}"
139+
done | format_output

0 commit comments

Comments
 (0)