2
0
mirror of https://github.com/munin-monitoring/contrib.git synced 2018-11-08 00:59:34 +01:00

Merge branch 'munin-plugins-busybox'

This commit is contained in:
Steve Schnepp 2013-01-28 13:42:20 +01:00
commit 7c5a9a8c58
17 changed files with 917 additions and 0 deletions

View File

@ -0,0 +1,17 @@
CC=gcc
CFLAGS=-W -Wall -pedantic -Wextra -g -O2
OBJS=main.o common.o cpu.o entropy.o forks.o fw_packets.o interrupts.o \
if_err_.o load.o open_files.o open_inodes.o processes.o swap.o uptime.o
LINKS=cpu entropy forks fw_packets interrupts if_err_eth0 load open_files \
open_inodes processes swap uptime
%.o:%.c
${CC} ${CFLAGS} -c $< -o $@
all:munin-plugins-busybox
strip -s munin-plugins-busybox
for l in ${LINKS}; do test -f $$l || ln -s munin-plugins-busybox $$l; done
munin-plugins-busybox:${OBJS}
${CC} ${CFLAGS} $^ -o $@
clean:
rm -f munin-plugins-busybox ${OBJS} ${LINKS}
.PHONY:all clean

View File

@ -0,0 +1,36 @@
What is this?
~~~~~~~~~~~~~
This is a rewrite of commonly used munin plugins in C as a single binary.
The purpose is reducing resource usage:
* disk space: the binary is smaler than the plugins together
* more diskspace: it has no dependencies on other programs
* less forks: it does not fork internally
* faster startup: it doesn't start perl or shell
* less memory: just a small C program
* less file accesses: one binary for many plugins
This can be useful for machines with restricted resources like embedded
machines.
What plugins are included?
~~~~~~~~~~~~~~~~~~~~~~~~~~
cpu entropy forks fw_packets interrupts load open_files open_inodes
processes swap uptime
Disadvantages?
~~~~~~~~~~~~~~
You lose flexibility. You can no longer just edit the plugin and if you try
you have to be very careful not to break it. If you want to deploy this you
have to create one binary for each architecture.
How to use?
~~~~~~~~~~~
After compiling there will be binary munin-plugins-busybox. You can just
replace symlinks in /etc/munin/plugins/ with symlinks to this binary.
License?
~~~~~~~~
(C) 2008 Helmut Grohne <helmut@subdivi.de>
At your choice GPLv2 or GPLv3 applies to *.c *.h and Makefile
# vim7:spelllang=en
# vim:textwidth=75

View File

@ -0,0 +1,14 @@
#include <stdio.h>
int writeyes(void) {
puts("yes");
return 0;
}
int writeno(const char *s) {
if(s)
printf("no (%s)\n", s);
else
puts("no");
return 1;
}

View File

@ -0,0 +1,9 @@
#ifndef COMMON_H
#define COMMON_H
#define PROC_STAT "/proc/stat"
int writeyes(void);
int writeno(const char *);
#endif

View File

@ -0,0 +1,157 @@
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <ctype.h>
#include <stdlib.h>
#include "common.h"
#define SYSWARNING 30
#define SYSCRITICAL 50
#define USRWARNING 80
int cpu(int argc, char **argv) {
FILE *f;
char buff[256], *s;
int ncpu=0, extinfo=0, scaleto100=0;
if(argc > 1) {
if(!strcmp(argv[1], "config")) {
s = getenv("scaleto100");
if(s && !strcmp(s, "yes"))
scaleto100=1;
if(!(f=fopen(PROC_STAT, "r"))) {
fputs("cannot open " PROC_STAT "\n", stderr);
return 1;
}
while(fgets(buff, 256, f)) {
if(!strncmp(buff, "cpu", 3)) {
if(isdigit(buff[3]))
ncpu++;
if(buff[3] == ' ') {
s = strtok(buff+4, " \t");
for(extinfo=0;strtok(NULL, " \t");extinfo++)
;
}
}
}
fclose(f);
if(ncpu < 1 || extinfo < 4) {
fputs("cannot parse " PROC_STAT "\n", stderr);
return 1;
}
puts("graph_title CPU usage");
if(extinfo == 7)
puts("graph_order system user nice idle iowait irq softirq");
else
puts("graph_order system user nice idle");
if(scaleto100)
puts("graph_args --base 1000 -r --lower-limit 0 --upper-limit 100");
else
printf("graph_args --base 1000 -r --lower-limit 0 --upper-limit %d\n", 100 * ncpu);
puts("graph_vlabel %\n"
"graph_scale no\n"
"graph_info This graph shows how CPU time is spent.\n"
"graph_category system\n"
"graph_period second\n"
"system.label system\n"
"system.draw AREA");
printf("system.max %d\n", 100 * ncpu);
puts("system.min 0\n"
"system.type DERIVE");
printf("system.warning %d\n", SYSWARNING * ncpu);
printf("system.critical %d\n", SYSCRITICAL * ncpu);
puts("system.info CPU time spent by the kernel in system activities\n"
"user.label user\n"
"user.draw STACK\n"
"user.min 0");
printf("user.max %d\n", 100 * ncpu);
printf("user.warning %d\n", USRWARNING * ncpu);
puts("user.type DERIVE\n"
"user.info CPU time spent by normal programs and daemons\n"
"nice.label nice\n"
"nice.draw STACK\n"
"nice.min 0");
printf("nice.max %d\n", 100 * ncpu);
puts("nice.type DERIVE\n"
"nice.info CPU time spent by nice(1)d programs\n"
"idle.label idle\n"
"idle.draw STACK\n"
"idle.min 0");
printf("idle.max %d\n", 100 * ncpu);
puts("idle.type DERIVE\n"
"idle.info Idle CPU time");
if(scaleto100)
printf("system.cdef system,%d,/\n"
"user.cdef user,%d,/\n"
"nice.cdef nice,%d,/\n"
"idle.cdef idle,%d,/\n", ncpu, ncpu, ncpu, ncpu);
if(extinfo == 7) {
puts("iowait.label iowait\n"
"iowait.draw STACK\n"
"iowait.min 0");
printf("iowait.max %d\n", 100 * ncpu);
puts("iowait.type DERIVE\n"
"iowait.info CPU time spent waiting for I/O operations to finish\n"
"irq.label irq\n"
"irq.draw STACK\n"
"irq.min 0");
printf("irq.max %d\n", 100 * ncpu);
puts("irq.type DERIVE\n"
"irq.info CPU time spent handling interrupts\n"
"softirq.label softirq\n"
"softirq.draw STACK\n"
"softirq.min 0");
printf("softirq.max %d\n", 100 * ncpu);
puts("softirq.type DERIVE\n"
"softirq.info CPU time spent handling \"batched\" interrupts");
if(scaleto100)
printf("iowait.cdef iowait,%d,/\n"
"irq.cdef irq,%d,/\n"
"softirq.cdef softirq,%d,/\n", ncpu, ncpu, ncpu);
}
return 0;
}
if(!strcmp(argv[1], "autoconf")) {
if(0 == access(PROC_STAT, R_OK))
return writeyes();
else
return writeno(PROC_STAT " not readable");
}
}
if(!(f=fopen(PROC_STAT, "r"))) {
fputs("cannot open " PROC_STAT "\n", stderr);
return 1;
}
while(fgets(buff, 256, f)) {
if(!strncmp(buff, "cpu ", 4)) {
fclose(f);
if(!(s = strtok(buff+4, " \t")))
break;
printf("user.value %s\n", s);
if(!(s = strtok(NULL, " \t")))
break;
printf("nice.value %s\n", s);
if(!(s = strtok(NULL, " \t")))
break;
printf("system.value %s\n", s);
if(!(s = strtok(NULL, " \t")))
break;
printf("idle.value %s\n", s);
if(!(s = strtok(NULL, " \t")))
return 0;
printf("iowait.value %s\n", s);
if(!(s = strtok(NULL, " \t")))
return 0;
printf("irq.value %s\n", s);
if(!(s = strtok(NULL, " \t")))
return 0;
printf("softirq.value %s\n", s);
return 0;
}
}
fclose(f);
fputs("no cpu line found in " PROC_STAT "\n", stderr);
return 1;
}

View File

@ -0,0 +1,37 @@
#include <string.h>
#include <stdio.h>
#include "common.h"
#define ENTROPY_AVAIL "/proc/sys/kernel/random/entropy_avail"
int entropy(int argc, char **argv) {
FILE *f;
int entropy;
if(argc > 1) {
if(!strcmp(argv[1], "config")) {
puts("graph_title Available entropy\n"
"graph_args --base 1000 -l 0\n"
"graph_vlabel entropy (bytes)\n"
"graph_scale no\n"
"graph_category system\n"
"graph_info This graph shows the amount of entropy available in the system.\n"
"entropy.label entropy\n"
"entropy.info The number of random bytes available. This is typically used by cryptographic applications.");
return 0;
}
if(!strcmp(argv[1], "autoconf"))
return writeyes();
}
if(!(f=fopen(ENTROPY_AVAIL, "r"))) {
fputs("cannot open " ENTROPY_AVAIL "\n", stderr);
return 1;
}
if(1 != fscanf(f, "%d", &entropy)) {
fputs("cannot read from " ENTROPY_AVAIL "\n", stderr);
fclose(f);
return 1;
}
fclose(f);
printf("entropy.value %d\n", entropy);
return 0;
}

View File

@ -0,0 +1,44 @@
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include "common.h"
int forks(int argc, char **argv) {
FILE *f;
char buff[256];
if(argc > 1) {
if(!strcmp(argv[1], "config")) {
puts("graph_title Fork rate\n"
"graph_args --base 1000 -l 0 \n"
"graph_vlabel forks / ${graph_period}\n"
"graph_category processes\n"
"graph_info This graph shows the forking rate (new processes started).\n"
"forks.label forks\n"
"forks.type DERIVE\n"
"forks.min 0\n"
"forks.max 100000\n"
"forks.info The number of forks per second.");
return 0;
}
if(!strcmp(argv[1], "autoconf")) {
if(0 == access(PROC_STAT, R_OK))
return writeyes();
else
return writeno(PROC_STAT " not readable");
}
}
if(!(f=fopen(PROC_STAT, "r"))) {
fputs("cannot open " PROC_STAT "\n", stderr);
return 1;
}
while(fgets(buff, 256, f)) {
if(!strncmp(buff, "processes ", 10)) {
fclose(f);
printf("forks.value %s", buff+10);
return 0;
}
}
fclose(f);
fputs("no processes line found in " PROC_STAT "\n", stderr);
return 1;
}

View File

@ -0,0 +1,62 @@
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <ctype.h>
#include "common.h"
#define PROC_NET_SNMP "/proc/net/snmp"
int fw_packets(int argc, char **argv) {
FILE *f;
char buff[1024], *s;
if(argc > 1) {
if(!strcmp(argv[1], "config")) {
puts("graph_title Firewall Throughput\n"
"graph_args --base 1000 -l 0\n"
"graph_vlabel Packets/${graph_period}\n"
"graph_category network\n"
"received.label Received\n"
"received.draw AREA\n"
"received.type DERIVE\n"
"received.min 0\n"
"forwarded.label Forwarded\n"
"forwarded.draw LINE2\n"
"forwarded.type DERIVE\n"
"forwarded.min 0");
return 0;
}
if(!strcmp(argv[1], "autoconf")) {
if(0 == access(PROC_NET_SNMP, R_OK))
return writeyes();
else
return writeno(PROC_NET_SNMP " not readable");
}
}
if(!(f=fopen(PROC_NET_SNMP, "r"))) {
fputs("cannot open " PROC_NET_SNMP "\n", stderr);
return 1;
}
while(fgets(buff, 1024, f)) {
if(!strncmp(buff, "Ip: ", 4) && isdigit(buff[4])) {
fclose(f);
if(!(s = strtok(buff+4, " \t")))
break;
if(!(s = strtok(NULL, " \t")))
break;
if(!(s = strtok(NULL, " \t")))
break;
printf("received.value %s\n", s);
if(!(s = strtok(NULL, " \t")))
break;
if(!(s = strtok(NULL, " \t")))
break;
if(!(s = strtok(NULL, " \t")))
break;
printf("forwarded.value %s\n", s);
return 0;
}
}
fclose(f);
fputs("no ip line found in " PROC_NET_SNMP "\n", stderr);
return 1;
}

View File

@ -0,0 +1,123 @@
#include <ctype.h>
#include <libgen.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define PROC_NET_DEV "/proc/net/dev"
int if_err_(int argc, char **argv) {
char *interface;
FILE *f;
char buff[256], *s;
int i;
interface = basename(argv[0]);
if(strncmp(interface, "if_err_", 7) != 0) {
fputs("if_err_ invoked with invalid basename\n", stderr);
return 1;
}
interface += 7;
if(argc > 1) {
if(!strcmp(argv[1], "autoconf")) {
if(access(PROC_NET_DEV, R_OK) == 0) {
puts("yes");
return 0;
} else {
puts("no (/proc/net/dev not found)");
return 1;
}
}
if(!strcmp(argv[1], "suggest")) {
if(NULL == (f = fopen(PROC_NET_DEV, "r")))
return 1;
while(fgets(buff, 256, f)) {
for(s=buff;*s == ' ';++s)
;
i = 0;
if(!strncmp(s, "eth", 3))
i = 3;
else if(!strncmp(s, "wlan", 4))
i = 4;
else if(!strncmp(s, "ath", 3))
i = 3;
else if(!strncmp(s, "ra", 2))
i = 2;
if(i == 0)
continue;
while(isdigit(s[i]))
++i;
if(s[i] != ':')
continue;
s[i] = '\0';
puts(s);
}
fclose(f);
return 0;
}
if(!strcmp(argv[1], "config")) {
puts("graph_order rcvd trans");
printf("graph_title %s errors\n", interface);
puts("graph_args --base 1000\n"
"graph_vlabel packets in (-) / out (+) per "
"${graph_period}\n"
"graph_category network");
printf("graph_info This graph shows the amount of "
"errors on the %s network interface.\n",
interface);
puts("rcvd.label packets\n"
"rcvd.type COUNTER\n"
"rcvd.graph no\n"
"rcvd.warning 1\n"
"trans.label packets\n"
"trans.type COUNTER\n"
"trans.negative rcvd\n"
"trans.warning 1");
return 0;
}
}
if(NULL == (f = fopen(PROC_NET_DEV, "r")))
return 1;
while(fgets(buff, 256, f)) {
for(s=buff;*s == ' ';++s)
;
if(0 != strncmp(s, interface, strlen(interface)))
continue;
s += strlen(interface);
if(*s != ':')
continue;
++s;
while(*s == ' ')
++s;
for(i=1;i<3;++i) {
while(isdigit(*s))
++s;
while(isspace(*s))
++s;
}
for(i=0;isdigit(s[i]);++i)
;
printf("rcvd.value ");
fwrite(s, 1, i, stdout);
putchar('\n');
s += i;
while(isspace(*s))
++s;
for(i=4;i<11;++i) {
while(isdigit(*s))
++s;
while(isspace(*s))
++s;
}
for(i=0;isdigit(s[i]);++i)
;
printf("trans.value ");
fwrite(s, 1, i, stdout);
putchar('\n');
}
return 0;
}

View File

@ -0,0 +1,47 @@
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include "common.h"
int interrupts(int argc, char **argv) {
FILE *f;
char buff[256];
if(argc > 1) {
if(!strcmp(argv[1], "config")) {
puts("graph_title Interrupts & context switches\n"
"graph_args --base 1000 -l 0\n"
"graph_vlabel interrupts & ctx switches / ${graph_period}\n"
"graph_category system\n"
"graph_info This graph shows the number of interrupts and context switches on the system. These are typically high on a busy system.\n"
"intr.info Interrupts are events that alter sequence of instructions executed by a processor. They can come from either hardware (exceptions, NMI, IRQ) or software.");
puts("ctx.info A context switch occurs when a multitasking operatings system suspends the currently running process, and starts executing another.\n"
"intr.label interrupts\n"
"ctx.label context switches\n"
"intr.type DERIVE\n"
"ctx.type DERIVE\n"
"intr.max 100000\n"
"ctx.max 100000\n"
"intr.min 0\n"
"ctx.min 0");
return 0;
}
if(!strcmp(argv[1], "autoconf")) {
if(0 == access(PROC_STAT, R_OK))
return writeyes();
else
return writeno(PROC_STAT " not readable");
}
}
if(!(f=fopen(PROC_STAT, "r"))) {
fputs("cannot open " PROC_STAT "\n", stderr);
return 1;
}
while(fgets(buff, 256, f)) {
if(!strncmp(buff, "intr ", 5))
printf("intr.value %s", buff+5);
else if(!strncmp(buff, "ctxt ", 5))
printf("ctx.value %s", buff+5);
}
fclose(f);
return 0;
}

View File

@ -0,0 +1,49 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "common.h"
#define PROC_LOADAVG "/proc/loadavg"
int load(int argc, char **argv) {
FILE *f;
int warn, crit;
float val;
char *s;
if(argc > 1) {
if(!strcmp(argv[1], "config")) {
s = getenv("load_warn");
if(s)
warn = atoi(s);
else
warn = 10;
s = getenv("load_crit");
if(s)
crit = atoi(s);
else
crit = 120;
puts("graph_title Load average\n"
"graph_args --base 1000 -l 0\n"
"graph_vlabel load\n"
"graph_scale no\n"
"graph_category system\n"
"load.label load");
printf("load.warning %d\nload.critical %d\n", warn, crit);
return 0;
}
if(!strcmp(argv[1], "autoconf"))
return writeyes();
}
if(!(f=fopen(PROC_LOADAVG, "r"))) {
fputs("cannot open " PROC_LOADAVG "\n", stderr);
return 1;
}
if(1 != fscanf(f, "%*f %f", &val)) {
fputs("cannot read from " PROC_LOADAVG "\n", stderr);
fclose(f);
return 1;
}
fclose(f);
printf("load.value %.2f\n", val);
return 0;
}

View File

@ -0,0 +1,67 @@
#include <libgen.h>
#include <string.h>
#include <stdio.h>
int cpu(int argc, char **argv);
int entropy(int argc, char **argv);
int forks(int argc, char **argv);
int fw_packets(int argc, char **argv);
int if_err_(int argc, char **argv);
int interrupts(int argc, char **argv);
int load(int argc, char **argv);
int open_files(int argc, char **argv);
int open_inodes(int argc, char **argv);
int processes(int argc, char **argv);
int swap(int argc, char **argv);
int uptime(int argc, char **argv);
int main(int argc, char **argv) {
char *progname;
progname = basename(argv[0]);
switch(*progname) {
case 'c':
if(!strcmp(progname+1, "pu"))
return cpu(argc, argv);
break;
case 'e':
if(!strcmp(progname+1, "ntropy"))
return entropy(argc, argv);
break;
case 'f':
if(!strcmp(progname+1, "orks"))
return forks(argc, argv);
if(!strcmp(progname+1, "w_packets"))
return fw_packets(argc, argv);
break;
case 'i':
if(!strcmp(progname+1, "nterrupts"))
return interrupts(argc, argv);
if(!strncmp(progname+1, "f_err_", 6))
return if_err_(argc, argv);
break;
case 'l':
if(!strcmp(progname+1, "oad"))
return load(argc, argv);
break;
case 'o':
if(!strcmp(progname+1, "pen_files"))
return open_files(argc, argv);
if(!strcmp(progname+1, "pen_inodes"))
return open_inodes(argc, argv);
break;
case 'p':
if(!strcmp(progname+1, "rocesses"))
return processes(argc, argv);
break;
case 's':
if(!strcmp(progname+1, "wap"))
return swap(argc, argv);
break;
case 'u':
if(!strcmp(progname+1, "ptime"))
return uptime(argc, argv);
break;
}
fprintf(stderr, "function not specified\n");
return 1;
}

View File

@ -0,0 +1,58 @@
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include "common.h"
#define FS_FILE_NR "/proc/sys/fs/file-nr"
int open_files(int argc, char **argv) {
FILE *f;
int alloc, freeh, avail;
if(argc > 1) {
if(!strcmp(argv[1], "config")) {
if(!(f=fopen(FS_FILE_NR, "r"))) {
fprintf(stderr, "cannot open " FS_FILE_NR "\n");
return 1;
}
if(1 != fscanf(f, "%*d %*d %d", &avail)) {
fclose(f);
fprintf(stderr, "cannot read from " FS_FILE_NR
"\n");
return 1;
}
fclose(f);
puts("graph_title File table usage\n"
"graph_args --base 1000 -l 0\n"
"graph_vlabel number of open files\n"
"graph_category system\n"
"graph_info This graph monitors the Linux open files table.\n"
"used.label open files\n"
"used.info The number of currently open files.\n"
"max.label max open files\n"
"max.info The maximum supported number of open "
"files. Tune by modifying " FS_FILE_NR
".");
printf("used.warning %d\nused.critical %d\n",
(int)(avail*0.92), (int)(avail*0.98));
return 0;
}
if(!strcmp(argv[1], "autoconf")) {
if(0 == access(FS_FILE_NR, R_OK))
return writeyes();
else
return writeno(FS_FILE_NR " not readable");
}
}
if(!(f=fopen(FS_FILE_NR, "r"))) {
fputs("cannot open " FS_FILE_NR "\n", stderr);
return 1;
}
if(3 != fscanf(f, "%d %d %d", &alloc, &freeh, &avail)) {
fclose(f);
fputs("cannot read from " FS_FILE_NR "\n", stderr);
return 1;
}
fclose(f);
printf("used.value %d\nmax.value %d\n", alloc-freeh, avail);
return 0;
}

View File

@ -0,0 +1,44 @@
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include "common.h"
#define FS_INODE_NR "/proc/sys/fs/inode-nr"
int open_inodes(int argc, char **argv) {
FILE *f;
int nr, freen;
if(argc > 1) {
if(!strcmp(argv[1], "config")) {
puts("graph_title Inode table usage\n"
"graph_args --base 1000 -l 0\n"
"graph_vlabel number of open inodes\n"
"graph_category system\n"
"graph_info This graph monitors the Linux open inode table.\n"
"used.label open inodes\n"
"used.info The number of currently open inodes.\n"
"max.label inode table size\n"
"max.info The size of the system inode table. This is dynamically adjusted by the kernel.");
return 0;
}
if(!strcmp(argv[1], "autoconf")) {
if(0 == access(FS_INODE_NR, R_OK))
return writeyes();
else
return writeno(FS_INODE_NR " not readable");
}
}
if(!(f=fopen(FS_INODE_NR, "r"))) {
fputs("cannot open " FS_INODE_NR "\n", stderr);
return 1;
}
if(2 != fscanf(f, "%d %d", &nr, &freen)) {
fclose(f);
fputs("cannot read from " FS_INODE_NR "\n", stderr);
return 1;
}
fclose(f);
printf("used.value %d\nmax.value %d\n", nr-freen, nr);
return 0;
}

View File

@ -0,0 +1,42 @@
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <ctype.h>
#include "common.h"
int processes(int argc, char **argv) {
DIR *d;
struct dirent *e;
char *s;
int n=0;
if(argc > 1) {
if(!strcmp(argv[1], "config")) {
puts("graph_title Number of Processes\n"
"graph_args --base 1000 -l 0 \n"
"graph_vlabel number of processes\n"
"graph_category processes\n"
"graph_info This graph shows the number of processes in the system.\n"
"processes.label processes\n"
"processes.draw LINE2\n"
"processes.info The current number of processes.");
return 0;
}
if(!strcmp(argv[1], "autoconf"))
return writeyes();
}
if(!(d = opendir("/proc"))) {
fputs("cannot open /proc\n", stderr);
return 1;
}
while((e = readdir(d))) {
for(s=e->d_name;*s;++s)
if(!isdigit(*s))
break;
if(!*s)
++n;
}
closedir(d);
printf("processes.value %d\n", n);
return 0;
}

View File

@ -0,0 +1,79 @@
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include "common.h"
int swap(int argc, char **argv) {
FILE *f;
char buff[256];
int in, out;
if(argc > 1) {
if(!strcmp(argv[1], "config")) {
puts("graph_title Swap in/out\n"
"graph_args -l 0 --base 1000\n"
"graph_vlabel pages per ${graph_period} in (-) / out (+)\n"
"graph_category system\n"
"swap_in.label swap\n"
"swap_in.type DERIVE\n"
"swap_in.max 100000\n"
"swap_in.min 0\n"
"swap_in.graph no\n"
"swap_out.label swap\n"
"swap_out.type DERIVE\n"
"swap_out.max 100000\n"
"swap_out.min 0\n"
"swap_out.negative swap_in");
return 0;
}
if(!strcmp(argv[1], "autoconf")) {
if(0 == access(PROC_STAT, R_OK))
return writeyes();
else
return writeno(PROC_STAT " not readable");
}
}
if(!access("/proc/vmstat", F_OK)) {
in=out=0;
if(!(f=fopen("/proc/vmstat", "r"))) {
fputs("cannot open /proc/vmstat\n", stderr);
return 1;
}
while(fgets(buff, 256, f)) {
if(!in && !strncmp(buff, "pswpin ", 7)) {
++in;
printf("swap_in.value %s", buff+7);
}
else if(!out && !strncmp(buff, "pswpout ", 8)) {
++out;
printf("swap_out.value %s", buff+8);
}
}
fclose(f);
if(!(in*out)) {
fputs("no usable data on /proc/vmstat\n", stderr);
return 1;
}
return 0;
} else {
if(!(f=fopen(PROC_STAT, "r"))) {
fputs("cannot open " PROC_STAT "\n", stderr);
return 1;
}
while(fgets(buff, 256, f)) {
if(!strncmp(buff, "swap ", 5)) {
fclose(f);
if(2 != sscanf(buff+5, "%d %d", &in, &out)) {
fputs("bad data on " PROC_STAT "\n",
stderr);
return 1;
}
printf("swap_in.value %d\nswap_out.value %d\n", in, out);
return 0;
}
}
fclose(f);
fputs("no swap line found in " PROC_STAT "\n", stderr);
return 1;
}
}

View File

@ -0,0 +1,32 @@
#include <stdio.h>
#include <string.h>
#include "common.h"
int uptime(int argc, char **argv) {
FILE *f;
float uptime;
if(argc > 1) {
if(!strcmp(argv[1], "config")) {
puts("graph_title Uptime\n"
"graph_args --base 1000 -l 0 \n"
"graph_vlabel uptime in days\n"
"uptime.label uptime\n"
"uptime.draw AREA");
return 0;
}
if(!strcmp(argv[1], "autoconf"))
return writeyes();
}
if(!(f=fopen("/proc/uptime", "r"))) {
fputs("cannot open /proc/uptime\n", stderr);
return 1;
}
if(1 != fscanf(f, "%f", &uptime)) {
fputs("cannot read from /proc/uptime\n", stderr);
fclose(f);
return 1;
}
fclose(f);
printf("uptime.value %.2f\n", uptime/86400);
return 0;
}