mirror of
https://github.com/munin-monitoring/contrib.git
synced 2025-07-21 18:41:03 +00:00
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.
This commit is contained in:
parent
914180fe54
commit
2fd3eec87c
1 changed files with 201 additions and 0 deletions
201
plugins/disk/smart-c/smart.c
Normal file
201
plugins/disk/smart-c/smart.c
Normal file
|
@ -0,0 +1,201 @@
|
|||
/*
|
||||
* Copyright (C) 2017 Bastiaan van Kesteren <bas@edeation.nl> - All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2 or v.3.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <libgen.h>
|
||||
#include <sys/wait.h>
|
||||
#include "common.h"
|
||||
|
||||
static char getitem(char *input, unsigned char item, char *output)
|
||||
{
|
||||
unsigned char i = 0;
|
||||
unsigned char seperators = 0;
|
||||
char know_this_seperator = 0;
|
||||
unsigned char start = 0;
|
||||
unsigned char stop = 0;
|
||||
|
||||
/* Trim starting spaces */
|
||||
while (input[i] == ' ') {
|
||||
i++;
|
||||
}
|
||||
|
||||
/* If we're requested to return the very first item... */
|
||||
if (seperators == item) {
|
||||
start = i;
|
||||
}
|
||||
|
||||
while (input[i] && seperators < item + 1) {
|
||||
if (input[i] == ' ') {
|
||||
if (know_this_seperator == 0) {
|
||||
know_this_seperator = 1;
|
||||
seperators++;
|
||||
if (seperators == item + 1) {
|
||||
stop = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (know_this_seperator) {
|
||||
know_this_seperator = 0;
|
||||
if (seperators == item) {
|
||||
start = i;
|
||||
}
|
||||
} else if (input[i] == '\n') {
|
||||
input[i] = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
if (stop) {
|
||||
/* Found stop, means we have a start aswell */
|
||||
strncpy(output, &input[start], stop - start);
|
||||
return 1;
|
||||
} else if (start) {
|
||||
/* Have a start, no stop. We're returning the last item of the string */
|
||||
strcpy(output, &input[start]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int smart(int argc, char **argv)
|
||||
{
|
||||
char command[50];
|
||||
char output[255];
|
||||
char label[25][100];
|
||||
char value[25][25];
|
||||
unsigned char attribute = 0;
|
||||
FILE *f;
|
||||
unsigned int i;
|
||||
|
||||
/* Prepare and execute command */
|
||||
snprintf(command, sizeof(command),
|
||||
"smartctl -A -d ata /dev/%s -n standby",
|
||||
&basename(argv[0])[6]);
|
||||
if ((f = popen(command, "r")) == 0) {
|
||||
return fail("cannot initiate command execution");
|
||||
}
|
||||
|
||||
/* Process command output */
|
||||
while (fgets(output, sizeof(output), f) != NULL) {
|
||||
printf("#%s", output);
|
||||
/* Filter out attribute lines; look for lines starting with an attribute ID */
|
||||
if ((output[0] >= '0' && output[0] <= '9') ||
|
||||
(output[0] == ' '
|
||||
&& (output[1] >= '0' && output[1] <= '9'))
|
||||
|| (output[0] == ' ' && output[1] == ' '
|
||||
&& (output[2] >= '0' && output[2] <= '9'))) {
|
||||
/* Now, print the 2nd column (attribute name) and the 10th (raw value) */
|
||||
|
||||
getitem(output, 1, label[attribute]);
|
||||
getitem(output, 9, value[attribute]);
|
||||
attribute++;
|
||||
if (attribute == 25) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Close command (this is where we get the exit code! */
|
||||
i = WEXITSTATUS(pclose(f));
|
||||
if (i == 1 || /* smartctl command did not parse */
|
||||
/*i == 2 || *//* smartctl device open failed */
|
||||
i == 127) { /* command not found */
|
||||
return fail("command execution failed");
|
||||
}
|
||||
|
||||
/* Setup for caching */
|
||||
snprintf(command, sizeof(command), "/mnt/ram/smart_%s",
|
||||
&basename(argv[0])[6]);
|
||||
|
||||
if (attribute == 0) {
|
||||
printf("#Cached attributes\n");
|
||||
/* No output from command, try to fetch attribute-list from disk with NaN values */
|
||||
if ((f = fopen(command, "r")) == 0) {
|
||||
return
|
||||
fail
|
||||
("command did not return data, no cached attribute-list");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (argc > 1) {
|
||||
if (strcmp(argv[1], "config") == 0) {
|
||||
printf
|
||||
("graph_title S.M.A.R.T values for drive %s\n"
|
||||
"graph_args --base 1000 --lower-limit 0\n"
|
||||
"graph_vlabel Attribute S.M.A.R.T value\n"
|
||||
"graph_category disk\n",
|
||||
&basename(argv[0])[6]);
|
||||
|
||||
if (attribute == 0) {
|
||||
while (fgets(output, sizeof(output), f) !=
|
||||
NULL) {
|
||||
for (i = 0; i < strlen(output);
|
||||
i++) {
|
||||
if (output[i] == '\n') {
|
||||
output[i] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("%s.label %s\n", output,
|
||||
output);
|
||||
}
|
||||
fclose(f);
|
||||
} else {
|
||||
f = fopen(command, "w");
|
||||
do {
|
||||
attribute--;
|
||||
printf("%s.label %s\n",
|
||||
label[attribute],
|
||||
label[attribute]);
|
||||
if (f) {
|
||||
fprintf(f, "%s\n",
|
||||
label[attribute]);
|
||||
}
|
||||
} while (attribute);
|
||||
|
||||
if (f) {
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
printf("standby.label standby\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Asking for a fetch */
|
||||
if (attribute == 0) {
|
||||
/* No data, use cached info */
|
||||
while (fgets(output, sizeof(output), f) != NULL) {
|
||||
for (i = 0; i < strlen(output); i++) {
|
||||
if (output[i] == '\n') {
|
||||
output[i] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("%s.value U\n", output);
|
||||
}
|
||||
printf("standby.value 1\n");
|
||||
fclose(f);
|
||||
} else {
|
||||
do {
|
||||
attribute--;
|
||||
printf("%s.value %s\n", label[attribute],
|
||||
value[attribute]);
|
||||
} while (attribute);
|
||||
printf("standby.value 0\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue