Commit 47c3e15d11b8888174b1b6e4bf202399b273ac94
1 parent
da7c8f92
Changed code style. Added 'optional' attribute field and another attribute for Intel Enterprise SSDs
Showing
2 changed files
with
74 additions
and
63 deletions
check_smart/check_smart.cpp
... | ... | @@ -2,76 +2,80 @@ |
2 | 2 | |
3 | 3 | const char *servicename = (const char*)"SMART"; |
4 | 4 | |
5 | -int getSmartAttrValue(string line) | |
6 | -{ | |
5 | +int getSmartAttrValue(string line) { | |
7 | 6 | return stoi(line.substr(line.find_last_of(" ")+1)); |
8 | 7 | } |
9 | 8 | |
10 | -int getSmartAttrID(string line) | |
11 | -{ | |
9 | +int getSmartAttrID(string line) { | |
12 | 10 | size_t first = line.find_first_not_of(' '); |
13 | 11 | size_t last = line.find_first_of(' ',first); |
14 | 12 | int id = -1; |
15 | - try {id = stoi(line.substr(first,last-first));} | |
16 | - catch(...){} | |
13 | + try { | |
14 | + id = stoi(line.substr(first,last-first)); | |
15 | + } | |
16 | + catch(...){ | |
17 | + return -1; | |
18 | + } | |
17 | 19 | return id; |
18 | 20 | } |
19 | 21 | |
20 | -int checkDriveType(const char* disk) | |
21 | -{ | |
22 | +int checkDriveType(const char* disk) { | |
22 | 23 | string output = ""; |
23 | 24 | string RRLine = ""; |
24 | 25 | string line= ""; |
25 | 26 | |
26 | 27 | int rc = run_smartctl_cmd(string(SMARTCTL_CMD_INFO), disk,&output); |
27 | - if(rc) | |
28 | - { | |
28 | + if(rc) { | |
29 | 29 | cout << "Error reading SMART data from disk " << disk << endl; |
30 | 30 | exit(3); |
31 | 31 | } |
32 | 32 | |
33 | 33 | stringstream sstream; |
34 | 34 | sstream.str(output); |
35 | - while(getline(sstream,line) && RRLine == "") | |
36 | - { | |
35 | + while(getline(sstream,line) && RRLine == "") { | |
37 | 36 | size_t found = line.find(ROTATION_INFO_STR); |
38 | - if(found != string::npos) {RRLine = line;} | |
37 | + if(found != string::npos) { | |
38 | + RRLine = line; | |
39 | + } | |
39 | 40 | } |
40 | - if(RRLine != "") | |
41 | - { | |
41 | + if(RRLine != "") { | |
42 | 42 | size_t found = RRLine.find(SSD_DEV_STR); |
43 | - if(found != string::npos) {return SSD;} | |
43 | + if(found != string::npos) { | |
44 | + return SSD; | |
45 | + } | |
44 | 46 | } |
45 | 47 | return HDD; |
46 | 48 | } |
47 | 49 | |
48 | -map<int,SMARTAttr> prepareAttrMap(int driveType) | |
49 | -{ | |
50 | +map<int,SMARTAttr> prepareAttrMap(int driveType) { | |
50 | 51 | map<int,SMARTAttr> map; |
51 | 52 | |
52 | 53 | SMARTAttr realloc; |
53 | 54 | realloc.name = "Reallocated_Sector_Ct"; |
54 | 55 | realloc.value = -1; |
55 | 56 | realloc.severity = WARN; |
57 | + realloc.optional = false; | |
56 | 58 | map[REALLOC_SEC_COUNT_ID] = realloc; |
57 | 59 | |
58 | 60 | SMARTAttr pending; |
59 | 61 | SMARTAttr off_uncorrect; |
60 | 62 | SMARTAttr wear; |
63 | + SMARTAttr wearout; | |
61 | 64 | SMARTAttr badblocks; |
62 | 65 | SMARTAttr rep_uncorrect; |
63 | 66 | |
64 | - switch(driveType) | |
65 | - { | |
67 | + switch(driveType) { | |
66 | 68 | case HDD: |
67 | 69 | pending.name = "Current_Pending_Sector"; |
68 | 70 | pending.value = -1; |
69 | 71 | pending.severity = CRIT; |
72 | + pending.optional = false; | |
70 | 73 | map[CURRENT_PENDING_SEC_ID] = pending; |
71 | 74 | |
72 | 75 | off_uncorrect.name = "Offline_Uncorrectable"; |
73 | 76 | off_uncorrect.value = -1; |
74 | 77 | off_uncorrect.severity = CRIT; |
78 | + off_uncorrect.optional = false; | |
75 | 79 | map[OFFLINE_UNCORRECT_ID] = off_uncorrect; |
76 | 80 | |
77 | 81 | break; |
... | ... | @@ -79,16 +83,25 @@ map<int,SMARTAttr> prepareAttrMap(int driveType) |
79 | 83 | wear.name = "Wear_Leveling_Count"; |
80 | 84 | wear.value = -1; |
81 | 85 | wear.severity = WARN; |
86 | + wear.optional = true; | |
82 | 87 | map[WEAR_COUNT_ID] = wear; |
83 | 88 | |
89 | + wearout.name = "Media_Wearout_Indicator"; | |
90 | + wearout.value = -1; | |
91 | + wearout.severity = WARN; | |
92 | + wearout.optional = true; | |
93 | + map[WEAR_COUNT_ID] = wearout; | |
94 | + | |
84 | 95 | badblocks.name = "Runtime_Bad_Block"; |
85 | 96 | badblocks.value = -1; |
86 | 97 | badblocks.severity = CRIT; |
98 | + badblocks.optional = false; | |
87 | 99 | map[RUNTIME_BAD_BLOCKS_IDD] = badblocks; |
88 | 100 | |
89 | 101 | rep_uncorrect.name = "Reported_Uncorrect"; |
90 | 102 | rep_uncorrect.value = -1; |
91 | 103 | rep_uncorrect.severity = CRIT; |
104 | + rep_uncorrect.optional = false; | |
92 | 105 | map[REP_UNCORRECT_ID] = rep_uncorrect; |
93 | 106 | |
94 | 107 | break; |
... | ... | @@ -96,14 +109,12 @@ map<int,SMARTAttr> prepareAttrMap(int driveType) |
96 | 109 | return map; |
97 | 110 | } |
98 | 111 | |
99 | -int evalStatus(const char* disk, int driveType, string *status) | |
100 | -{ | |
112 | +int evalStatus(const char* disk, int driveType, string *status) { | |
101 | 113 | string output = ""; |
102 | 114 | string line = ""; |
103 | 115 | |
104 | 116 | int rc = run_smartctl_cmd(string(SMARTCTL_CMD_ATTRS), disk,&output); |
105 | - if(rc) | |
106 | - { | |
117 | + if(rc) { | |
107 | 118 | cout << "Error reading SMART data from disk " << disk << endl; |
108 | 119 | exit(UNKN); |
109 | 120 | } |
... | ... | @@ -112,34 +123,42 @@ int evalStatus(const char* disk, int driveType, string *status) |
112 | 123 | |
113 | 124 | stringstream sstream; |
114 | 125 | sstream.str(output); |
115 | - while(getline(sstream,line)) | |
116 | - { | |
117 | - for(map<int,SMARTAttr>::iterator it = attrMap.begin(); it != attrMap.end(); ++it) | |
118 | - { | |
126 | + while(getline(sstream,line)) { | |
127 | + for(map<int,SMARTAttr>::iterator it = attrMap.begin(); it != attrMap.end(); ++it) { | |
119 | 128 | int id = it->first; |
120 | - if(getSmartAttrID(line) == id) {attrMap[id].value = getSmartAttrValue(line);} | |
129 | + int attrID = getSmartAttrID(line); | |
130 | + if(attrID == -1) { | |
131 | + continue; | |
132 | + } | |
133 | + if(getSmartAttrID(line) == id) { | |
134 | + attrMap[id].value = getSmartAttrValue(line); | |
135 | + } | |
121 | 136 | } |
122 | 137 | } |
123 | 138 | int ret = OK; |
124 | 139 | *status = string(disk); |
125 | - for(map<int,SMARTAttr>::iterator it = attrMap.begin(); it != attrMap.end(); ++it) | |
126 | - { | |
140 | + for(map<int,SMARTAttr>::iterator it = attrMap.begin(); it != attrMap.end(); ++it) { | |
127 | 141 | int id = it->first; |
128 | 142 | SMARTAttr attr = it->second; |
129 | 143 | |
130 | - if(attr.value == -1) | |
131 | - { | |
144 | + if(attr.value == -1) { | |
145 | + if(attr.optional) { | |
146 | + continue; | |
147 | + } | |
132 | 148 | *status = string(disk) + " status UNKNOWN"; |
133 | 149 | return UNKN; |
134 | 150 | } |
135 | 151 | int veredict = 0; |
136 | - if(attr.value) {veredict = attr.severity;} | |
137 | - switch(veredict) | |
138 | - { | |
152 | + if(attr.value) { | |
153 | + veredict = attr.severity; | |
154 | + } | |
155 | + switch(veredict) { | |
139 | 156 | case OK: |
140 | 157 | break; |
141 | 158 | case WARN: |
142 | - if(ret == OK) {ret = WARN;} | |
159 | + if(ret == OK) { | |
160 | + ret = WARN; | |
161 | + } | |
143 | 162 | break; |
144 | 163 | case CRIT: |
145 | 164 | ret = CRIT; |
... | ... | @@ -150,8 +169,7 @@ int evalStatus(const char* disk, int driveType, string *status) |
150 | 169 | return ret; |
151 | 170 | } |
152 | 171 | |
153 | -int run_smartctl_cmd(const string command, const char* disk, string* output) | |
154 | -{ | |
172 | +int run_smartctl_cmd(const string command, const char* disk, string* output) { | |
155 | 173 | int uid = getuid(); |
156 | 174 | setreuid(0,0); |
157 | 175 | |
... | ... | @@ -161,15 +179,12 @@ int run_smartctl_cmd(const string command, const char* disk, string* output) |
161 | 179 | return rc; |
162 | 180 | } |
163 | 181 | |
164 | -void printVersion() | |
165 | -{ | |
182 | +void printVersion() { | |
166 | 183 | cout << "check_smart v" << VERSION << endl << endl; |
167 | 184 | } |
168 | 185 | |
169 | -void printHelp(bool longVersion) | |
170 | -{ | |
171 | - if(longVersion) | |
172 | - { | |
186 | +void printHelp(bool longVersion) { | |
187 | + if(longVersion) { | |
173 | 188 | printVersion(); |
174 | 189 | cout << "Checks for pending, reallocated or uncorrectable sectors in disks using SMART" << endl << "WARNING: Requires the setuid bit to be set to run as root" << endl << endl; |
175 | 190 | printHelp(false); |
... | ... | @@ -185,8 +200,7 @@ void printHelp(bool longVersion) |
185 | 200 | cout << "Usage: " << endl << "check_smart [-hV] DISKS..." << endl << endl; |
186 | 201 | } |
187 | 202 | |
188 | -void set_timeout(unsigned int sec) | |
189 | -{ | |
203 | +void set_timeout(unsigned int sec) { | |
190 | 204 | struct itimerval timer; |
191 | 205 | timer.it_value.tv_sec = sec; |
192 | 206 | timer.it_value.tv_usec = 0; |
... | ... | @@ -200,14 +214,11 @@ void set_timeout(unsigned int sec) |
200 | 214 | sigaction (SIGVTALRM, &sa, 0); |
201 | 215 | } |
202 | 216 | |
203 | -int main(int argc, char **argv) | |
204 | -{ | |
217 | +int main(int argc, char **argv) { | |
205 | 218 | set_timeout(10); |
206 | 219 | int c; |
207 | - while ((c = getopt (argc, argv, "Vh")) != -1) | |
208 | - { | |
209 | - switch(c) | |
210 | - { | |
220 | + while ((c = getopt (argc, argv, "Vh")) != -1) { | |
221 | + switch(c) { | |
211 | 222 | case 'h': |
212 | 223 | printHelp(true); |
213 | 224 | return OK; |
... | ... | @@ -220,8 +231,7 @@ int main(int argc, char **argv) |
220 | 231 | } |
221 | 232 | } |
222 | 233 | |
223 | - if(argc == 1) | |
224 | - { | |
234 | + if(argc == 1) { | |
225 | 235 | cout << "No disks checked" << endl; |
226 | 236 | return 3; |
227 | 237 | } |
... | ... | @@ -229,11 +239,9 @@ int main(int argc, char **argv) |
229 | 239 | string *results = new string[argc-1]; |
230 | 240 | int returnCode = OK; |
231 | 241 | |
232 | - for(int i = 1; i < argc; i++) | |
233 | - { | |
242 | + for(int i = 1; i < argc; i++) { | |
234 | 243 | int driveType = checkDriveType(argv[i]); |
235 | - switch(driveType) | |
236 | - { | |
244 | + switch(driveType) { | |
237 | 245 | case HDD: |
238 | 246 | case SSD: |
239 | 247 | break; |
... | ... | @@ -243,8 +251,7 @@ int main(int argc, char **argv) |
243 | 251 | break; |
244 | 252 | } |
245 | 253 | |
246 | - switch(evalStatus(argv[i],driveType,&(results[i-1]))) | |
247 | - { | |
254 | + switch(evalStatus(argv[i],driveType,&(results[i-1]))) { | |
248 | 255 | case OK: |
249 | 256 | break; |
250 | 257 | case WARN: |
... | ... | @@ -253,6 +260,9 @@ int main(int argc, char **argv) |
253 | 260 | case CRIT: |
254 | 261 | returnCode = CRIT; |
255 | 262 | break; |
263 | + case UNKN: | |
264 | + returnCode = UNKN; | |
265 | + break; | |
256 | 266 | } |
257 | 267 | } |
258 | 268 | |
... | ... | @@ -261,8 +271,7 @@ int main(int argc, char **argv) |
261 | 271 | else if(returnCode == WARN) {cout << " WARNING - disk status: ";} |
262 | 272 | else if(returnCode == CRIT) {cout << " CRITICAL - disk status: ";} |
263 | 273 | else if(returnCode == UNKN) {cout << " UNKNOWN - disk status: ";} |
264 | - for(int i = 0; i < (argc-1); i++) | |
265 | - { | |
274 | + for(int i = 0; i < (argc-1); i++) { | |
266 | 275 | cout << results[i]; |
267 | 276 | if(i != (argc-2)) {cout << ", ";} |
268 | 277 | } | ... | ... |
check_smart/check_smart.h
... | ... | @@ -31,6 +31,7 @@ |
31 | 31 | #define CURRENT_PENDING_SEC_ID 197 |
32 | 32 | #define OFFLINE_UNCORRECT_ID 198 |
33 | 33 | #define WEAR_COUNT_ID 177 |
34 | +#define MEDIA_WEAROUT_INDICATOR 233 | |
34 | 35 | #define RUNTIME_BAD_BLOCKS_IDD 183 |
35 | 36 | #define REP_UNCORRECT_ID 187 |
36 | 37 | |
... | ... | @@ -44,6 +45,7 @@ struct SMARTAttr |
44 | 45 | string name; |
45 | 46 | int value; |
46 | 47 | int severity; |
48 | + bool optional; | |
47 | 49 | }; typedef struct SMARTAttr SMARTAttr; |
48 | 50 | |
49 | 51 | ... | ... |