]>
Commit | Line | Data |
---|---|---|
cae5b340 AX |
1 | #!/bin/sh |
2 | # | |
3 | # Show SMART stats | |
4 | # | |
5 | ||
6 | helpstr=" | |
7 | smart: Show SMART temperature and error stats (specific to drive type) | |
8 | smartx: Show SMART extended drive stats (specific to drive type). | |
9 | temp: Show SMART drive temperature in celsius (all drives). | |
10 | health: Show reported SMART status (all drives). | |
11 | r_proc: Show SMART read GBytes processed over drive lifetime (SAS). | |
12 | w_proc: Show SMART write GBytes processed over drive lifetime (SAS). | |
13 | r_ucor: Show SMART read uncorrectable errors (SAS). | |
14 | w_ucor: Show SMART write uncorrectable errors (SAS). | |
15 | nonmed: Show SMART non-medium errors (SAS). | |
16 | defect: Show SMART grown defect list (SAS). | |
17 | hours_on: Show number of hours drive powered on (all drives). | |
18 | realloc: Show SMART reallocated sectors count (ATA). | |
19 | rep_ucor: Show SMART reported uncorrectable count (ATA). | |
20 | cmd_to: Show SMART command timeout count (ATA). | |
21 | pend_sec: Show SMART current pending sector count (ATA). | |
22 | off_ucor: Show SMART offline uncorrectable errors (ATA). | |
23 | ata_err: Show SMART ATA errors (ATA). | |
24 | pwr_cyc: Show SMART power cycle count (ATA). | |
25 | serial: Show disk serial number. | |
26 | " | |
27 | ||
28 | script=$(basename "$0") | |
29 | ||
30 | if [ "$1" = "-h" ] ; then | |
31 | echo "$helpstr" | grep "$script:" | tr -s '\t' | cut -f 2- | |
32 | exit | |
33 | fi | |
34 | ||
35 | smartctl_path=$(which smartctl) | |
36 | ||
37 | if [ -b "$VDEV_UPATH" ] && [ -x "$smartctl_path" ]; then | |
38 | raw_out=$(eval "sudo $smartctl_path -a $VDEV_UPATH") | |
39 | ||
40 | # Are we a SAS or ATA drive? Look for the right line in smartctl: | |
41 | # | |
42 | # SAS: | |
43 | # Transport protocol: SAS | |
44 | # | |
45 | # SATA: | |
46 | # ATA Version is: 8 | |
47 | # | |
48 | type=$(echo "$raw_out" | grep -m 1 -Eo '^ATA|SAS$') | |
49 | out=$(echo "$raw_out" | awk ' | |
50 | # SAS specific | |
51 | /read:/{print "rrd="$4"\nr_cor="$5"\nr_proc="$7"\nr_ucor="$8} | |
52 | /write:/{print "rwr="$4"\nw_cor="$5"\nw_proc="$7"\nw_ucor="$8} | |
53 | /Non-medium error count/{print "nonmed="$4} | |
54 | /Elements in grown defect list/{print "defect="$6} | |
55 | ||
56 | # SAS common | |
57 | /Drive Temperature:/{print "temp="$4} | |
58 | # Status can be a long string, substitute spaces for '_' | |
59 | /SMART Health Status:/{printf "health="; for(i=4;i<=NF-1;i++){printf "%s_", $i}; printf "%s\n", $i} | |
60 | /number of hours powered up/{print "hours_on="$7} | |
61 | /Serial number:/{print "serial="$3} | |
62 | ||
63 | # SATA specific | |
64 | /Reallocated_Sector_Ct/{print "realloc="$10} | |
65 | /Reported_Uncorrect/{print "rep_ucor="$10} | |
66 | /Command_Timeout/{print "cmd_to="$10} | |
67 | /Current_Pending_Sector/{print "pend_sec="$10} | |
68 | /Offline_Uncorrectable/{print "off_ucor="$10} | |
69 | /ATA Error Count:/{print "ata_err="$4} | |
70 | /Power_Cycle_Count/{print "pwr_cyc="$10} | |
71 | ||
72 | # SATA common | |
73 | /Temperature_Celsius/{print "temp="$10} | |
74 | /SMART overall-health self-assessment test result:/{print "health="$6} | |
75 | /Power_On_Hours/{print "hours_on="$10} | |
76 | /Serial Number:/{print "serial="$3} | |
77 | ||
78 | END {ORS="\n"; print ""} | |
79 | '); | |
80 | fi | |
81 | ||
82 | # if type is not set by now, either we don't have a block device | |
83 | # or smartctl failed. Either way, default to ATA and set out to | |
84 | # nothing | |
85 | if [ -z "$type" ]; then | |
86 | type="ATA" | |
87 | out= | |
88 | fi | |
89 | ||
90 | case $script in | |
91 | smart) | |
92 | # Print temperature plus common predictors of drive failure | |
93 | if [ "$type" = "SAS" ] ; then | |
94 | scripts="temp|health|r_ucor|w_ucor" | |
95 | elif [ "$type" = "ATA" ] ; then | |
96 | scripts="temp|health|ata_err|realloc|rep_ucor|cmd_to|pend_sec|off_ucor" | |
97 | fi | |
98 | ;; | |
99 | smartx) | |
100 | # Print some other interesting stats | |
101 | if [ "$type" = "SAS" ] ; then | |
102 | scripts="hours_on|defect|nonmed|r_proc|w_proc" | |
103 | elif [ "$type" = "ATA" ] ; then | |
104 | scripts="hours_on|pwr_cyc" | |
105 | fi | |
106 | ;; | |
107 | *) | |
108 | scripts="$script" | |
109 | esac | |
110 | ||
111 | with_vals=$(echo "$out" | grep -E "$scripts") | |
112 | if [ ! -z "$with_vals" ]; then | |
113 | echo "$with_vals" | |
114 | without_vals=$(echo "$scripts" | tr "|" "\n" | | |
115 | grep -v -E "$(echo "$with_vals" | | |
116 | awk -F "=" '{print $1}')" | awk '{print $0"="}') | |
117 | else | |
118 | without_vals=$(echo "$scripts" | tr "|" "\n" | awk '{print $0"="}') | |
119 | fi | |
120 | ||
121 | if [ ! -z "$without_vals" ]; then | |
122 | echo "$without_vals" | |
123 | fi |