Projet

Général

Profil

Révision 2fd3eec8

ID2fd3eec87cb97967f911c2b240d279b67d33c774
Parent 914180fe
Enfant a420c4eb

Ajouté par Bastiaan van Kesteren il y a presque 5 ans

Hacked together a smart_ plugin in C

There is some trickery going on to not wakeup the disk when it's in standby

Note: this was aimed at munin-c, but was rejected since it uses a
subprocess that calls the `smartctl` tool.

Voir les différences:

plugins/disk/smart-c/smart.c
1
/*
2
 * Copyright (C) 2017 Bastiaan van Kesteren <bas@edeation.nl> - All rights reserved.
3
 *
4
 * This copyrighted material is made available to anyone wishing to use,
5
 * modify, copy, or redistribute it subject to the terms and conditions
6
 * of the GNU General Public License v.2 or v.3.
7
 */
8

  
9
#include <stdlib.h>
10
#include <stdio.h>
11
#include <unistd.h>
12
#include <string.h>
13
#include <libgen.h>
14
#include <sys/wait.h>
15
#include "common.h"
16

  
17
static char getitem(char *input, unsigned char item, char *output)
18
{
19
	unsigned char i = 0;
20
	unsigned char seperators = 0;
21
	char know_this_seperator = 0;
22
	unsigned char start = 0;
23
	unsigned char stop = 0;
24

  
25
	/* Trim starting spaces */
26
	while (input[i] == ' ') {
27
		i++;
28
	}
29

  
30
	/* If we're requested to return the very first item... */
31
	if (seperators == item) {
32
		start = i;
33
	}
34

  
35
	while (input[i] && seperators < item + 1) {
36
		if (input[i] == ' ') {
37
			if (know_this_seperator == 0) {
38
				know_this_seperator = 1;
39
				seperators++;
40
				if (seperators == item + 1) {
41
					stop = i;
42
					break;
43
				}
44
			}
45
		} else if (know_this_seperator) {
46
			know_this_seperator = 0;
47
			if (seperators == item) {
48
				start = i;
49
			}
50
		} else if (input[i] == '\n') {
51
			input[i] = 0;
52
			break;
53
		}
54

  
55
		i++;
56
	}
57

  
58
	if (stop) {
59
		/* Found stop, means we have a start aswell */
60
		strncpy(output, &input[start], stop - start);
61
		return 1;
62
	} else if (start) {
63
		/* Have a start, no stop. We're returning the last item of the string */
64
		strcpy(output, &input[start]);
65
		return 1;
66
	}
67

  
68
	return 0;
69
}
70

  
71
int smart(int argc, char **argv)
72
{
73
	char command[50];
74
	char output[255];
75
	char label[25][100];
76
	char value[25][25];
77
	unsigned char attribute = 0;
78
	FILE *f;
79
	unsigned int i;
80

  
81
	/* Prepare and execute command */
82
	snprintf(command, sizeof(command),
83
		 "smartctl -A -d ata /dev/%s -n standby",
84
		 &basename(argv[0])[6]);
85
	if ((f = popen(command, "r")) == 0) {
86
		return fail("cannot initiate command execution");
87
	}
88

  
89
	/* Process command output */
90
	while (fgets(output, sizeof(output), f) != NULL) {
91
		printf("#%s", output);
92
		/* Filter out attribute lines; look for lines starting with an attribute ID */
93
		if ((output[0] >= '0' && output[0] <= '9') ||
94
		    (output[0] == ' '
95
		     && (output[1] >= '0' && output[1] <= '9'))
96
		    || (output[0] == ' ' && output[1] == ' '
97
			&& (output[2] >= '0' && output[2] <= '9'))) {
98
			/* Now, print the 2nd column (attribute name) and the 10th (raw value) */
99

  
100
			getitem(output, 1, label[attribute]);
101
			getitem(output, 9, value[attribute]);
102
			attribute++;
103
			if (attribute == 25) {
104
				break;
105
			}
106
		}
107
	}
108

  
109
	/* Close command (this is where we get the exit code! */
110
	i = WEXITSTATUS(pclose(f));
111
	if (i == 1 ||		/* smartctl command did not parse */
112
	    /*i == 2 || *//* smartctl device open failed */
113
	    i == 127) {		/* command not found */
114
		return fail("command execution failed");
115
	}
116

  
117
	/* Setup for caching */
118
	snprintf(command, sizeof(command), "/mnt/ram/smart_%s",
119
		 &basename(argv[0])[6]);
120

  
121
	if (attribute == 0) {
122
		printf("#Cached attributes\n");
123
		/* No output from command, try to fetch attribute-list from disk with NaN values */
124
		if ((f = fopen(command, "r")) == 0) {
125
			return
126
			    fail
127
			    ("command did not return data, no cached attribute-list");
128
			return 0;
129
		}
130
	}
131

  
132
	if (argc > 1) {
133
		if (strcmp(argv[1], "config") == 0) {
134
			printf
135
			    ("graph_title S.M.A.R.T values for drive %s\n"
136
			     "graph_args --base 1000 --lower-limit 0\n"
137
			     "graph_vlabel Attribute S.M.A.R.T value\n"
138
			     "graph_category disk\n",
139
			     &basename(argv[0])[6]);
140

  
141
			if (attribute == 0) {
142
				while (fgets(output, sizeof(output), f) !=
143
				       NULL) {
144
					for (i = 0; i < strlen(output);
145
					     i++) {
146
						if (output[i] == '\n') {
147
							output[i] = '\0';
148
							break;
149
						}
150
					}
151
					printf("%s.label %s\n", output,
152
					       output);
153
				}
154
				fclose(f);
155
			} else {
156
				f = fopen(command, "w");
157
				do {
158
					attribute--;
159
					printf("%s.label %s\n",
160
					       label[attribute],
161
					       label[attribute]);
162
					if (f) {
163
						fprintf(f, "%s\n",
164
							label[attribute]);
165
					}
166
				} while (attribute);
167

  
168
				if (f) {
169
					fclose(f);
170
				}
171
			}
172
			printf("standby.label standby\n");
173
			return 0;
174
		}
175
	}
176

  
177
	/* Asking for a fetch */
178
	if (attribute == 0) {
179
		/* No data, use cached info */
180
		while (fgets(output, sizeof(output), f) != NULL) {
181
			for (i = 0; i < strlen(output); i++) {
182
				if (output[i] == '\n') {
183
					output[i] = '\0';
184
					break;
185
				}
186
			}
187
			printf("%s.value U\n", output);
188
		}
189
		printf("standby.value 1\n");
190
		fclose(f);
191
	} else {
192
		do {
193
			attribute--;
194
			printf("%s.value %s\n", label[attribute],
195
			       value[attribute]);
196
		} while (attribute);
197
		printf("standby.value 0\n");
198
	}
199

  
200
	return 0;
201
}

Formats disponibles : Unified diff