diff --git a/tools/munin-plugins-busybox/Makefile b/tools/munin-plugins-busybox/Makefile new file mode 100644 index 00000000..fe465f64 --- /dev/null +++ b/tools/munin-plugins-busybox/Makefile @@ -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 diff --git a/tools/munin-plugins-busybox/README b/tools/munin-plugins-busybox/README new file mode 100644 index 00000000..4f8c56be --- /dev/null +++ b/tools/munin-plugins-busybox/README @@ -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 +At your choice GPLv2 or GPLv3 applies to *.c *.h and Makefile + +# vim7:spelllang=en +# vim:textwidth=75 diff --git a/tools/munin-plugins-busybox/common.c b/tools/munin-plugins-busybox/common.c new file mode 100644 index 00000000..3d78e518 --- /dev/null +++ b/tools/munin-plugins-busybox/common.c @@ -0,0 +1,14 @@ +#include + +int writeyes(void) { + puts("yes"); + return 0; +} + +int writeno(const char *s) { + if(s) + printf("no (%s)\n", s); + else + puts("no"); + return 1; +} diff --git a/tools/munin-plugins-busybox/common.h b/tools/munin-plugins-busybox/common.h new file mode 100644 index 00000000..8db440a9 --- /dev/null +++ b/tools/munin-plugins-busybox/common.h @@ -0,0 +1,9 @@ +#ifndef COMMON_H +#define COMMON_H + +#define PROC_STAT "/proc/stat" + +int writeyes(void); +int writeno(const char *); + +#endif diff --git a/tools/munin-plugins-busybox/cpu.c b/tools/munin-plugins-busybox/cpu.c new file mode 100644 index 00000000..9f3483f8 --- /dev/null +++ b/tools/munin-plugins-busybox/cpu.c @@ -0,0 +1,157 @@ +#include +#include +#include +#include +#include +#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; +} diff --git a/tools/munin-plugins-busybox/entropy.c b/tools/munin-plugins-busybox/entropy.c new file mode 100644 index 00000000..cc7791fd --- /dev/null +++ b/tools/munin-plugins-busybox/entropy.c @@ -0,0 +1,37 @@ +#include +#include +#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; +} diff --git a/tools/munin-plugins-busybox/forks.c b/tools/munin-plugins-busybox/forks.c new file mode 100644 index 00000000..3d4a198e --- /dev/null +++ b/tools/munin-plugins-busybox/forks.c @@ -0,0 +1,44 @@ +#include +#include +#include +#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; +} diff --git a/tools/munin-plugins-busybox/fw_packets.c b/tools/munin-plugins-busybox/fw_packets.c new file mode 100644 index 00000000..8e94fdea --- /dev/null +++ b/tools/munin-plugins-busybox/fw_packets.c @@ -0,0 +1,62 @@ +#include +#include +#include +#include +#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; +} diff --git a/tools/munin-plugins-busybox/if_err_.c b/tools/munin-plugins-busybox/if_err_.c new file mode 100644 index 00000000..caee6b3a --- /dev/null +++ b/tools/munin-plugins-busybox/if_err_.c @@ -0,0 +1,123 @@ +#include +#include +#include +#include +#include + +#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; +} diff --git a/tools/munin-plugins-busybox/interrupts.c b/tools/munin-plugins-busybox/interrupts.c new file mode 100644 index 00000000..8c800c61 --- /dev/null +++ b/tools/munin-plugins-busybox/interrupts.c @@ -0,0 +1,47 @@ +#include +#include +#include +#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; +} diff --git a/tools/munin-plugins-busybox/load.c b/tools/munin-plugins-busybox/load.c new file mode 100644 index 00000000..27e18437 --- /dev/null +++ b/tools/munin-plugins-busybox/load.c @@ -0,0 +1,49 @@ +#include +#include +#include +#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; +} diff --git a/tools/munin-plugins-busybox/main.c b/tools/munin-plugins-busybox/main.c new file mode 100644 index 00000000..b1833a04 --- /dev/null +++ b/tools/munin-plugins-busybox/main.c @@ -0,0 +1,67 @@ +#include +#include +#include + +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; +} diff --git a/tools/munin-plugins-busybox/open_files.c b/tools/munin-plugins-busybox/open_files.c new file mode 100644 index 00000000..9eb5c3d7 --- /dev/null +++ b/tools/munin-plugins-busybox/open_files.c @@ -0,0 +1,58 @@ +#include +#include +#include +#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; +} diff --git a/tools/munin-plugins-busybox/open_inodes.c b/tools/munin-plugins-busybox/open_inodes.c new file mode 100644 index 00000000..d9e86577 --- /dev/null +++ b/tools/munin-plugins-busybox/open_inodes.c @@ -0,0 +1,44 @@ +#include +#include +#include +#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; +} diff --git a/tools/munin-plugins-busybox/processes.c b/tools/munin-plugins-busybox/processes.c new file mode 100644 index 00000000..b5227686 --- /dev/null +++ b/tools/munin-plugins-busybox/processes.c @@ -0,0 +1,42 @@ +#include +#include +#include +#include +#include +#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; +} diff --git a/tools/munin-plugins-busybox/swap.c b/tools/munin-plugins-busybox/swap.c new file mode 100644 index 00000000..3decfbb0 --- /dev/null +++ b/tools/munin-plugins-busybox/swap.c @@ -0,0 +1,79 @@ +#include +#include +#include +#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; + } +} diff --git a/tools/munin-plugins-busybox/uptime.c b/tools/munin-plugins-busybox/uptime.c new file mode 100644 index 00000000..ce6093fa --- /dev/null +++ b/tools/munin-plugins-busybox/uptime.c @@ -0,0 +1,32 @@ +#include +#include +#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; +}