mirror of
https://github.com/munin-monitoring/contrib.git
synced 2025-07-22 02:51:03 +00:00
Merge branch 'master' of git://github.com/munin-monitoring/contrib
This commit is contained in:
commit
1edc7e7dc3
10 changed files with 541 additions and 48 deletions
10
README.md
10
README.md
|
@ -5,7 +5,9 @@
|
|||
**This is usually where you want to begin your journey.**
|
||||
|
||||
Here you'll find all the plugins coming from http://exchange.munin-monitoring.org/.
|
||||
It as evolved since then, but
|
||||
That web site is for the time being disabled, new updates are done here.
|
||||
|
||||
If a dedicated website comes back alive, its plugin backend will be this git repo.
|
||||
|
||||
## contrib/templates/ - 3rd-party templates
|
||||
|
||||
|
@ -25,3 +27,9 @@ Here, you can put just any kind of tool. Please use this directory instead of a
|
|||
It makes things way more easy to search for others.
|
||||
|
||||
And, it serves as an incubator of SVN `trunk/contrib` :-)
|
||||
|
||||
## Notes to contributors
|
||||
|
||||
We like to have ''elementary'' commits (a good rationale is : one per Changelog entry), as it is much easier to manage for reviewing. Debugging is also usually easier that way.
|
||||
|
||||
So please **don't** be afraid to make as many commits as needed.
|
||||
|
|
98
plugins/gunicorn/gunicorn_memory_status
Executable file
98
plugins/gunicorn/gunicorn_memory_status
Executable file
|
@ -0,0 +1,98 @@
|
|||
#!/usr/bin/env python
|
||||
"""
|
||||
gunicorn_status - A munin plugin for Linux to monitor the memory
|
||||
usage of gunicorn processes
|
||||
|
||||
Copyright (C) 2012 Azavea, Inc.
|
||||
Author: Andrew Jennings
|
||||
|
||||
Like Munin, this plugin is licensed under the GNU GPL v2 license
|
||||
http://www.opensource.org/licenses/GPL-2.0
|
||||
|
||||
If you've put your gunicorn pid somewhere other than the
|
||||
default /var/run/gunicorn.pid, you can add a section like
|
||||
this to your munin-node's plugin configuration:
|
||||
|
||||
[gunicorn_*]
|
||||
env.gunicorn_pid_path [path to your gunicorn pid]
|
||||
|
||||
This plugin supports the following munin configuration parameters:
|
||||
#%# family=auto contrib
|
||||
#%# capabilities=autoconf
|
||||
|
||||
"""
|
||||
|
||||
import sys, os
|
||||
from subprocess import check_output
|
||||
|
||||
# set path to your gunicorn pid
|
||||
try:
|
||||
GUNICORN_PID_PATH = os.environ['gunicorn_pid_path']
|
||||
except:
|
||||
GUNICORN_PID_PATH = "/var/run/gunicorn.pid"
|
||||
|
||||
|
||||
class GunicornMemoryStatus():
|
||||
master_pid = ''
|
||||
"""
|
||||
The Gunicorn master process pid, as a string
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
try:
|
||||
self._get_master_pid()
|
||||
except:
|
||||
raise Exception("Couldn't read gunicorn pid information")
|
||||
|
||||
|
||||
def print_total_memory(self):
|
||||
print ('total_memory.value %d' % self._get_total_memory())
|
||||
|
||||
|
||||
def _get_master_pid(self):
|
||||
master_pid_file = open(GUNICORN_PID_PATH)
|
||||
self.master_pid = master_pid_file.read().rstrip()
|
||||
master_pid_file.close()
|
||||
return True
|
||||
|
||||
def _get_total_memory(self):
|
||||
master = self._get_master_memory()
|
||||
total = master +self. _get_worker_memory()
|
||||
total_in_mb = total / 1024
|
||||
return total_in_mb
|
||||
|
||||
def _get_master_memory(self):
|
||||
master = int(check_output(
|
||||
['ps', '--pid', self.master_pid, '-o', 'rss', '--no-headers']))
|
||||
return master
|
||||
|
||||
def _get_worker_memory(self):
|
||||
worker_processes = check_output(
|
||||
['ps', '--ppid', self.master_pid, '-o', 'rss', '--no-headers'])
|
||||
process_memory_usage = [int(rss) for rss in worker_processes.splitlines()]
|
||||
worker_memory_usage = sum(process_memory_usage)
|
||||
return worker_memory_usage
|
||||
|
||||
def print_config():
|
||||
print "graph_title Gunicorn - Memory Usage"
|
||||
print "graph_args --base 1024 -l 0"
|
||||
print "graph_vlabel Megabytes"
|
||||
print "graph_category gunicorn"
|
||||
print "total_memory.label Total Memory"
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) == 2 and sys.argv[1] == 'config':
|
||||
print_config()
|
||||
elif len(sys.argv) == 2 and sys.argv[1] == 'autoconf':
|
||||
try:
|
||||
open(GUNICORN_PID_PATH).close()
|
||||
print "yes"
|
||||
except:
|
||||
print "no"
|
||||
# Some docs say it'll be called with fetch, some say no arg at all
|
||||
elif len(sys.argv) == 1 or (len(sys.argv) == 2 and sys.argv[1] == 'fetch'):
|
||||
try:
|
||||
status = GunicornMemoryStatus()
|
||||
status.print_total_memory()
|
||||
except:
|
||||
sys.exit("Couldn't retrieve gunicorn memory usage information")
|
113
plugins/gunicorn/gunicorn_status
Executable file
113
plugins/gunicorn/gunicorn_status
Executable file
|
@ -0,0 +1,113 @@
|
|||
#!/usr/bin/env python
|
||||
"""
|
||||
gunicorn_status - A munin plugin for Linux to monitor gunicorn processes
|
||||
|
||||
Copyright (C) 2012 Azavea, Inc.
|
||||
Author: Andrew Jennings
|
||||
|
||||
Like Munin, this plugin is licensed under the GNU GPL v2 license
|
||||
http://www.opensource.org/licenses/GPL-2.0
|
||||
|
||||
If you've put your gunicorn pid somewhere other than the
|
||||
default /var/run/gunicorn.pid, you can add a section like
|
||||
this to your munin-node's plugin configuration:
|
||||
|
||||
[gunicorn_*]
|
||||
env.gunicorn_pid_path [path to your gunicorn pid]
|
||||
|
||||
This plugin supports the following munin configuration parameters:
|
||||
#%# family=auto contrib
|
||||
#%# capabilities=autoconf
|
||||
|
||||
"""
|
||||
|
||||
import sys, os
|
||||
from subprocess import check_output
|
||||
from time import sleep
|
||||
|
||||
# set path to your gunicorn pid
|
||||
try:
|
||||
GUNICORN_PID_PATH = os.environ['gunicorn_pid_path']
|
||||
except:
|
||||
GUNICORN_PID_PATH = "/var/run/gunicorn.pid"
|
||||
|
||||
class GunicornStatus():
|
||||
master_pid = ''
|
||||
"""
|
||||
The gunicorn master process pid, as a string
|
||||
"""
|
||||
|
||||
worker_pids = ''
|
||||
"""
|
||||
The list of gunicorn processes as strings
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
try:
|
||||
self._get_master_pid()
|
||||
self._get_worker_pids(self.master_pid)
|
||||
except:
|
||||
sys.exit("Couldn't read gunicorn pid")
|
||||
|
||||
def print_total_workers(self):
|
||||
print ('total_workers.value %d' % self._worker_count())
|
||||
|
||||
def print_idle_workers(self):
|
||||
print ('idle_workers.value %d' % self._idle_worker_count())
|
||||
|
||||
|
||||
def _get_master_pid(self):
|
||||
master_pid_file = open(GUNICORN_PID_PATH)
|
||||
self.master_pid = master_pid_file.read().rstrip()
|
||||
master_pid_file.close()
|
||||
|
||||
def _get_worker_pids(self, master_pid):
|
||||
children = check_output(
|
||||
['ps', '--ppid', master_pid, '-o', 'pid', '--no-headers'])
|
||||
self.worker_pids = [pid.strip() for pid in children.splitlines()]
|
||||
|
||||
def _worker_count(self):
|
||||
return len(self.worker_pids)
|
||||
|
||||
def _idle_worker_count(self):
|
||||
idle_workers = 0
|
||||
for pid in self.worker_pids:
|
||||
before = self._cpu_time(pid)
|
||||
sleep(0.50)
|
||||
after = self._cpu_time(pid)
|
||||
if before == after:
|
||||
idle_workers += 1
|
||||
return idle_workers
|
||||
|
||||
def _cpu_time(self, pid):
|
||||
proc_info = open('/proc/%s/stat' % pid).read()
|
||||
proc_info = [field.rstrip() for field in proc_info.split()]
|
||||
user_time = int(proc_info[13].rstrip())
|
||||
kernel_time = int(proc_info[14].rstrip())
|
||||
return user_time + kernel_time
|
||||
|
||||
def print_config():
|
||||
print "graph_title Gunicorn - Status"
|
||||
print "graph_args -l 0"
|
||||
print "graph_vlabel Number of workers"
|
||||
print "graph_category gunicorn"
|
||||
print "total_workers.label Total Workers"
|
||||
print "idle_workers.label Idle Workers"
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) == 2 and sys.argv[1] == 'config':
|
||||
print_config()
|
||||
elif len(sys.argv) == 2 and sys.argv[1] == 'autoconf':
|
||||
try:
|
||||
open(GUNICORN_PID_PATH).close()
|
||||
print "yes"
|
||||
except:
|
||||
print "no"
|
||||
# Some docs say it'll be called with fetch, some say no arg at all
|
||||
elif len(sys.argv) == 1 or (len(sys.argv) == 2 and sys.argv[1] == 'fetch'):
|
||||
status = GunicornStatus()
|
||||
try:
|
||||
status.print_total_workers()
|
||||
status.print_idle_workers()
|
||||
except:
|
||||
sys.exit("Couldn't retrieve gunicorn status")
|
|
@ -13,7 +13,7 @@ Requires perl and either WWW::Mechanize or Net::Telnet.
|
|||
=head1 CONFIGURATION
|
||||
|
||||
The plugin needs HTML access to the router. If you can get to http://YOUR_ROUTER/,
|
||||
and are greeting with a page titled "THOMSON TG585 v7", then you can probably use this plugin.
|
||||
and are greeting with a page titled "THOMSON TG585 v7", then you can probably use this plugin.
|
||||
|
||||
This is a wildcard plugin, so you will need to create symlinks to this plugin (or create copies if your filesystem doesn't support linking). Links should be of the form:
|
||||
|
||||
|
@ -1112,25 +1112,45 @@ else {
|
|||
|
||||
sub TelnetError {
|
||||
my $errmsg = shift;
|
||||
my @parts;
|
||||
if ( $mode eq 'bandwidth' ) {
|
||||
@parts = qw(down up);
|
||||
}
|
||||
elsif ( $mode eq 'power' ) {
|
||||
@parts = qw(downout upout downline upline downsn upsn);
|
||||
}
|
||||
elsif ( $mode eq 'uptime' ) {
|
||||
@parts = qw(Box DSL iNet);
|
||||
}
|
||||
elsif ( $mode eq 'errors' ) {
|
||||
@parts = qw(downFEC upFEC downCRC upCRC downHEC upHEC);
|
||||
}
|
||||
foreach (@parts) {
|
||||
my %parts = (
|
||||
'atm' => [qw(RXCells RxErrors RxOctets TxCells TxErrors TxOctets)],
|
||||
'bandwidth' => [qw(down downrate up uprate)],
|
||||
'conntrack' =>
|
||||
[qw(Active closing expected halfopen ICMP idle loose mcast non TCP TCPclosing TCPestablished TCPopen UDP)],
|
||||
'dhcpclient' =>
|
||||
[qw(ACKs Corrupted DECLINEs DISCOVERs failures INFORMs NAKs OFFERs Other RELEASEs REPLIES REQUESTs)],
|
||||
'dhcprelay' =>
|
||||
[qw(badc bogusg bogusr clientp corrupta missinga missingc packets serverp)],
|
||||
'dhcpserver' =>
|
||||
[qw(ACKs BOOTP Corrupted DECLINE DISCOVER dropped failures INFORM NAKs OFFERs Other RELEASE REQUEST)],
|
||||
'dns' =>
|
||||
[qw(corrupted discard external forwarded negative resolved spoofed spurious unknown)],
|
||||
'errors' => [qw(downCRC downFEC downHEC upCRC upFEC upHEC)],
|
||||
'firewall' =>
|
||||
[qw(DroppedForward DroppedInput DroppedOutput ParsedForward ParsedInput ParsedOutput)],
|
||||
'ids' => [qw(Active Collisions New Recycled Searches)],
|
||||
'igmphost' =>
|
||||
[qw(badchecksum badqueries badttl failing invalidmembership norouter receivedforour reportsreceived reportstransmitted toolong toosmall v1membershipq v2membershipq v3membershipq v3membershipr)],
|
||||
'igmpproxy' =>
|
||||
[qw(badchecksum badleavereports badqueries badreports badttl election igmpleavereports mrdadvertise mrdbad mrdsolicits mrdterminate noroute queriesfail toolong tooshort v1queriesr v1queriess v1reportsr v2queriesr v2queriess v2reportsr v3queriesr v3queriess v3reportsr)],
|
||||
'power' => [qw(downline downout downsn upline upout upsn)],
|
||||
'protoicmp' =>
|
||||
[qw(echor echorepr echoreps echos errorsr errorss maskr maskrepr maskreps masks paramr params quenchr quenchs redirectr redirects timeexceedr timeexceeds timestampr timestamprepr timestampreps timestamps unreachabler unreachables)],
|
||||
'protoip' =>
|
||||
[qw(droppedfrags forwarded fragerrs fragged fragments fwderrors herrors hostdrop hostfwd hostrec noroute reassembled reserrors totfrags)],
|
||||
'prototcp' =>
|
||||
[qw(accepts attempts drops errors established received retransmitted transmitted)],
|
||||
'protoudp' => [qw(dropped errors received transmitted)],
|
||||
'uptime' => [qw(Box DSL iNet)]
|
||||
);
|
||||
|
||||
foreach ( @{$parts{$mode}} ) {
|
||||
print "$_.value U\n";
|
||||
print "$_.extinfo $errmsg\n";
|
||||
}
|
||||
print "# Sending \"exit\"\n" if $MUNIN_DEBUG;
|
||||
if ( defined $telnet ) {
|
||||
$telnet->errmode('return');
|
||||
$telnet->print('exit');
|
||||
$telnet->close;
|
||||
}
|
||||
|
@ -1141,7 +1161,8 @@ else {
|
|||
$telnet = new Net::Telnet(
|
||||
Host => $host,
|
||||
Prompt => '/{.*}.*=>$/',
|
||||
ErrMode => \&TelnetError
|
||||
ErrMode => \&TelnetError,
|
||||
Timeout => 10
|
||||
);
|
||||
|
||||
print "# Logging in...\n" if $MUNIN_DEBUG;
|
||||
|
|
50
plugins/php/php_apc.php
Normal file
50
plugins/php/php_apc.php
Normal file
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
$ret = array();
|
||||
|
||||
if(function_exists("apc_cache_info") && function_exists("apc_sma_info"))
|
||||
{
|
||||
switch ($_GET["act"])
|
||||
{
|
||||
case "memory":
|
||||
$tmp = apc_sma_info();
|
||||
$ret["mem_used"] = $tmp["seg_size"]-$tmp["avail_mem"];
|
||||
$ret["mem_avail"] = $tmp["avail_mem"];
|
||||
break;
|
||||
case "hits":
|
||||
$tmp = apc_cache_info();
|
||||
$ret["num_hits"] = $tmp["num_hits"];
|
||||
$ret["num_misses"] = $tmp["num_misses"];
|
||||
break;
|
||||
case "percents":
|
||||
$tmp = apc_sma_info();
|
||||
$ret["memory"] = 100-(($tmp["avail_mem"] / $tmp["seg_size"])*100);
|
||||
$tmp = apc_cache_info();
|
||||
$ret["hits"] = ($tmp["num_hits"] / ( $tmp["num_hits"]+$tmp["num_misses"]) ) * 100;
|
||||
$ret["misses"] = ($tmp["num_misses"] / ( $tmp["num_hits"]+$tmp["num_misses"]) ) * 100;
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
switch ($_GET["act"])
|
||||
{
|
||||
case "memory":
|
||||
$ret["mem_size"] = 0;
|
||||
$ret["mem_used"] = 0;
|
||||
break;
|
||||
case "hits":
|
||||
$ret["num_hits"] = 0;
|
||||
$ret["num_misses"] = 0;
|
||||
break;
|
||||
case "percents":
|
||||
$ret["memory"] = 0;
|
||||
$ret["hits"] = 0;
|
||||
$ret["misses"] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
foreach($ret as $key => $val) echo "$key.value $val\n";
|
||||
|
||||
?>
|
Binary file not shown.
|
@ -96,8 +96,8 @@ $graphsRef->{listeners} = {
|
|||
info => 'This graph shows us the various counts for listener states we are tracking',
|
||||
},
|
||||
datasrc => [
|
||||
{ name => 'maxlisteners', draw => 'STACK', min => '0', label => 'Max Listeners', type => 'GAUGE' },
|
||||
{ name => 'currlisteners', draw => 'AREA', min => '0', label => 'Current Listeners', type => 'GAUGE' },
|
||||
{ name => 'maxlisteners', draw => 'AREA', min => '0', label => 'Max Listeners', type => 'GAUGE' },
|
||||
{ name => 'currlisteners', draw => 'STACK', min => '0', label => 'Current Listeners', type => 'GAUGE' },
|
||||
],
|
||||
};
|
||||
|
||||
|
@ -121,8 +121,8 @@ $graphsRef->{sid_listeners} = {
|
|||
info => 'This graph shows us the various counts for listener states we are tracking',
|
||||
},
|
||||
datasrc => [
|
||||
{ name => 'maxlisteners', draw => 'STACK', min => '0', label => 'Max Listeners', type => 'GAUGE', xmlkey => 'MAXLISTENERS' },
|
||||
{ name => 'currlisteners', draw => 'AREA', min => '0', label => 'Current Listeners', type => 'GAUGE', xmlkey => 'CURRENTLISTENERS' },
|
||||
{ name => 'maxlisteners', draw => 'AREA', min => '0', label => 'Max Listeners', type => 'GAUGE', xmlkey => 'MAXLISTENERS' },
|
||||
{ name => 'currlisteners', draw => 'STACK', min => '0', label => 'Current Listeners', type => 'GAUGE', xmlkey => 'CURRENTLISTENERS' },
|
||||
{ name => 'peaklisteners', draw => 'LINE2', min => '0', label => 'Peak Listeners', type => 'GAUGE', xmlkey => 'PEAKLISTENERS' },
|
||||
{ name => 'uniqlisteners', draw => 'LINE2', min => '0', label => 'Unique Listeners', type => 'GAUGE', xmlkey => 'UNIQUELISTENERS' },
|
||||
],
|
||||
|
@ -133,7 +133,7 @@ if (defined($ARGV[0]) && ($ARGV[0] eq 'config')) {
|
|||
exit;
|
||||
}
|
||||
|
||||
if (defined($ARGV[0]) && ($ARGV[0] eq 'autoconf')) {
|
||||
if (defined($ARGV[0]) && (($ARGV[0] eq 'autoconf') || ($ARGV[0] eq 'suggest'))) {
|
||||
check_autoconf();
|
||||
exit;
|
||||
}
|
||||
|
@ -234,7 +234,7 @@ sub print_listener_data {
|
|||
}
|
||||
}
|
||||
}
|
||||
print "multigraph shoutcast2_active\n";
|
||||
print "multigraph shoutcast2_listeners\n";
|
||||
foreach my $dsrc (@{$graphsRef->{listeners}->{datasrc}}) {
|
||||
if ($dsrc->{name} eq 'maxlisteners') {
|
||||
print "$dsrc->{name}.value $maxListeners\n";
|
|
@ -17,26 +17,19 @@ style="AREA"
|
|||
cpus=$(grep -c ^processor /proc/cpuinfo)
|
||||
|
||||
run_watchdog() { # should also trap kill and term signals
|
||||
while :; do
|
||||
sleep ${watchdog:-600}
|
||||
touch -d now-${timeout:-1200}sec $cache
|
||||
[ $pidfile -nt $cache ] || break
|
||||
done
|
||||
[ -f $pidfile ] || exit # may have been removed by terminating daemon
|
||||
kill $(cat $pidfile)
|
||||
rm -f $pidfile $cache
|
||||
kill -0 $(cat $pidfile) 2> /dev/null || rm -f $pidfile
|
||||
}
|
||||
|
||||
|
||||
run_acquire() {
|
||||
echo "$$" > $pidfile
|
||||
$pluginfull watchdog &
|
||||
mpstat -P ALL $interval |
|
||||
awk -v cpus=$cpus '$2>=0&&$2<10 {print $2, systime(), (100-$11)/cpus}' >> $cache
|
||||
rm -f $pidfile $cache
|
||||
}
|
||||
|
||||
run_daemon() {
|
||||
run_watchdog
|
||||
if [ -f $pidfile ]; then
|
||||
touch $pidfile
|
||||
else
|
||||
|
@ -92,4 +85,3 @@ exit 0
|
|||
# acquire which needs a different pid than watchdog, otherwise watchdog
|
||||
# could/will kill itself when expiring before the watched process is killed.
|
||||
# not a POSIX feature.
|
||||
|
|
@ -1,23 +1,26 @@
|
|||
#!/usr/local/bin/perl -w
|
||||
#!/usr/bin/env perl
|
||||
# -*- perl -*-
|
||||
# Plugin to monitor number of irqs
|
||||
# Plugin to monitor the system uptime
|
||||
#
|
||||
#%# family=auto
|
||||
#%# capabilities=autoconf
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
my %IN;
|
||||
|
||||
my $sysctl = defined($ENV{sysctl}) ? $ENV{sysctl} : '/sbin/sysctl';
|
||||
my $ostype = `uname -s`;
|
||||
chomp ($ostype);
|
||||
|
||||
if (defined($ARGV[0]) and ($ARGV[0] eq 'autoconf')) {
|
||||
if ( -x $sysctl ) {
|
||||
print "yes\n";
|
||||
}else{
|
||||
print "no (sysctl binary not found)\n";
|
||||
};
|
||||
exit;
|
||||
if ( -x $sysctl ) {
|
||||
print "yes\n";
|
||||
} else {
|
||||
print "no (sysctl binary not found)\n";
|
||||
};
|
||||
exit;
|
||||
};
|
||||
|
||||
if (defined($ARGV[0]) and ($ARGV[0] eq 'config')) {
|
||||
|
@ -26,12 +29,12 @@ graph_title Uptime
|
|||
graph_args --base 1000 -l 0
|
||||
graph_vlabel days
|
||||
graph_category system
|
||||
compile.label kernel age
|
||||
compile.label Kernel age
|
||||
compile.type GAUGE
|
||||
compile.min 0
|
||||
compile.max 1000
|
||||
compile.draw AREA
|
||||
uptime.label uptime
|
||||
uptime.label Uptime
|
||||
uptime.type GAUGE
|
||||
uptime.min 0
|
||||
uptime.max 1000
|
||||
|
@ -44,13 +47,15 @@ use Date::Parse;
|
|||
|
||||
my $kern=`sysctl -n kern.version`;
|
||||
$kern=~ /:\s+(.*\S)\s+\w+\@/;
|
||||
print "Compile: $1\n";
|
||||
#print "Compile: $1\n";
|
||||
$kern=str2time($1);
|
||||
|
||||
my $boot=`sysctl -n kern.boottime`;
|
||||
$boot=~ / sec = (\d+)/;
|
||||
print "Boot: $1\n";
|
||||
$boot=$1;
|
||||
my $boot=`sysctl -n kern.boottime`; # OpenBSD will return seconds from the epoch
|
||||
if ($ostype ne "OpenBSD") {
|
||||
$boot=~ / sec = (\d+)/;
|
||||
#print "Boot: $1\n";
|
||||
$boot=$1;
|
||||
}
|
||||
|
||||
my $now=time;
|
||||
|
||||
|
|
206
tools/munin-cli/munin
Executable file
206
tools/munin-cli/munin
Executable file
|
@ -0,0 +1,206 @@
|
|||
#!/bin/bash
|
||||
# Munin CLI
|
||||
# Found on http://munin.scarydevilmonastery.net/
|
||||
|
||||
# ----- munin plugin management script -----
|
||||
# munin [ restart | permissions | active | available | bak | help]
|
||||
# munin [ <enable | disable | edit | purge> <plugin>]
|
||||
# munin [ run <plugin [command]>]
|
||||
|
||||
# munin restart reloads munin config, through init.d script
|
||||
# munin permissions edit /etc/munin/plugin-conf.d/munin-node
|
||||
# munin active list enabled plugins
|
||||
# munin available list all plugins from repositiories except the active ones
|
||||
# munin run plugin execute plugin through munin-run
|
||||
# munin run plugin config execute config section of plugin through munin-run
|
||||
# munin run plugin autoconf execute config section of plugin through munin-run
|
||||
# munin enable plugin symlink to plugin and reload munin config
|
||||
# munin disable plugin remove symlink to plugin and reload munin config
|
||||
# munin purge plugin remove symlin to plugin, its .rrd files and the associated .html files
|
||||
# munin edit plugin open plugin in editor
|
||||
# munin export plugin copy plugin to other server(s)
|
||||
# munin bak remove *~ files from plugin repository directories
|
||||
# munin template plugin start editing a new plugin
|
||||
# munin pack create archive, containing plugins
|
||||
# munin help print overview of commands
|
||||
# munin print overview of commands
|
||||
|
||||
# multiple plugin repositories are supported.
|
||||
# running without arguments shows a command overview
|
||||
|
||||
# depends on external programs:
|
||||
# stat, sed, find, sort, uniq.
|
||||
|
||||
versions="yes"
|
||||
plugins=(/usr/local/share/munin/plugins /usr/share/munin/plugins) # where are plugins kept? First path is local, where new plugins from template are added
|
||||
munin="/etc/munin/plugins" # munin enabled plugins (symlinks to plugins) are here
|
||||
trash="$HOME/.Trash" # where to move files of purged plugins to?
|
||||
host="localhost"
|
||||
domain="localdomain"
|
||||
servers="" # list of machines to export plugins to
|
||||
muninlib="/var/lib/munin/$domain" # rrd files store
|
||||
muninweb="/var/www/munin/$domain" # html files store
|
||||
muninhost=$host.$domain
|
||||
permissions="/etc/munin/plugin-conf.d/munin-node"
|
||||
archive="/var/www/plugins/munin-plugins.tgz" # munin pack updates this archive, for downloading through web server
|
||||
autopack="no" # update $archive after edit
|
||||
|
||||
plugin="$2"
|
||||
wildcard="$3"
|
||||
|
||||
# editor choice: if not specified in environment variable EDIT, use environment variables EDITOR, then VISUAL
|
||||
# if still no success, try executable "editor", and if still no editor found, hardcode to /usr/bin/vi. I know that
|
||||
# this looks funny, but these are legal bashisms.
|
||||
: ${EDIT:=${EDITOR:-${VISUAL:-"$(which editor)"}}}
|
||||
: ${EDIT:="/usr/bin/vi"}
|
||||
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
required="chase sort grep sed uniq find stat munin-run scp"
|
||||
# chase instead of readlink -f because it can handle wildcards
|
||||
|
||||
for require in $required; do
|
||||
type -t $require > /dev/null ||
|
||||
echo "warning: required program $require not found"
|
||||
done
|
||||
|
||||
checkin() {
|
||||
[[ $versions == yes ]] && mkdir -p $(dirname $1)/RCS && ci -l -mautocheckin $1
|
||||
}
|
||||
|
||||
munin_active() { stat -c%N $munin/* ;} # show enabled plugins
|
||||
munin_run() { munin-run $plugin $wildcard ;} # run a plugin with munin-run
|
||||
|
||||
munin_restart() { # restart munin-node
|
||||
echo -n restarting munin node...
|
||||
/etc/init.d/munin-node restart &> /dev/null
|
||||
echo done
|
||||
}
|
||||
|
||||
munin_available() { # show available, inactive plugins
|
||||
(find ${plugins[*]} -maxdepth 1 -type f ;
|
||||
chase $munin/*) |
|
||||
sort | uniq -u
|
||||
}
|
||||
|
||||
|
||||
munin_disable() { # removes plugin or link from $munin
|
||||
if [[ -z "$plugin" ]] ; then munin_active ; exit 1 ; fi
|
||||
if [[ ! -z "$wildcard" ]] ; then plugin+="_$wildcard" ; fi
|
||||
if [[ ! -h $munin/$plugin ]] ; then
|
||||
if [[ ! -f $munin/$plugin ]] ; then echo "plugin not enabled" ; exit 1 ; fi
|
||||
fi
|
||||
echo removing $munin/$plugin ; rm $munin/$plugin && munin_restart
|
||||
}
|
||||
|
||||
findplugin() {
|
||||
for pluginpath in ${plugins[*]} ; do
|
||||
if [[ -f "$pluginpath/$1" ]] ; then
|
||||
echo "$pluginpath"
|
||||
break
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
munin_enable() { # creates a link to plugin in $munin
|
||||
if [[ -z "$plugin" ]] ; then munin_available ; exit 1 ; fi
|
||||
if [[ -f $munin/$plugin ]] ; then echo plugin already enabled ; exit 0 ; fi
|
||||
usepath=$(findplugin "$plugin")
|
||||
if [[ -z "$usepath" ]] ; then echo plugin not found ; exit 1 ; fi
|
||||
source="$plugin"
|
||||
chmod +x "${usepath}/${source}"
|
||||
if [[ ! -z "$wildcard" ]] ; then plugin+="$wildcard" ; fi
|
||||
ln -s "${usepath}/${source}" "${munin}/${plugin}"
|
||||
echo "enabled $(stat -c%N ${munin}/${plugin})"
|
||||
echo "-------------------------------------------------------------------"
|
||||
echo "plugin output:"
|
||||
munin-run "${plugin}"
|
||||
echo "-------------------------------------------------------------------"
|
||||
munin_restart
|
||||
}
|
||||
|
||||
|
||||
munin_purge() { # move link, web files and rrd file to $trash
|
||||
if mkdir -p "$trash" ; then
|
||||
munin_disable $plugin
|
||||
cleanplugin="${plugin//.-/_}"
|
||||
ls $muninlib/$muninhost-$cleanplugin-*.rrd
|
||||
mv $muninlib/$muninhost-$cleanplugin-*.rrd "$trash"
|
||||
else
|
||||
echo "can't access $trash dir"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
munin_pack() { # pack all plugins into a tgz archive
|
||||
tar cpzf "$archive" ${plugins[@]//plugins/plugins/* }
|
||||
}
|
||||
|
||||
munin_edit() { # edit plugin source of an active plugin
|
||||
plugintarget=$(chase "$munin/$plugin")
|
||||
if [[ -z "$plugintarget" ]] ; then
|
||||
pluginpath=$(findplugin "$plugin")
|
||||
if [[ -z "$pluginpath" ]] ; then
|
||||
echo "plugin not found"
|
||||
exit 1
|
||||
fi
|
||||
plugintarget="$pluginpath/$plugin"
|
||||
fi
|
||||
$EDIT "$plugintarget"
|
||||
checkin "$plugintarget"
|
||||
[[ "$autopack" == "yes" ]] && munin_pack
|
||||
}
|
||||
|
||||
munin_permissions() { # edit plugin permissions file
|
||||
CHANGED=$(stat -c%Y $permissions)
|
||||
$EDIT $permissions
|
||||
(( CHANGED == $(stat -c%Y $permissions) )) || munin_restart
|
||||
}
|
||||
|
||||
munin_bak() { # remove files ending in ~ as left by joe as backup files
|
||||
for pluginpath in ${plugins[*]} ; do
|
||||
ls $pluginpath/*~ 2> /dev/null && rm $pluginpath/*~
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
|
||||
munin_template() { # start editing a new plugin, using template
|
||||
echo $plugin
|
||||
if [[ -f ${plugins}/$plugin ]]; then
|
||||
echo "$plugin already exists"
|
||||
else
|
||||
cp ${plugins}/template ${plugins}/$plugin
|
||||
munin edit $plugin
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
munin_migrate() { # move system plugin to local plugins, relink if necessary
|
||||
if [[ -f ${plugins[1]}/$plugin ]]; then
|
||||
plugintarget=$(chase "$munin/$plugin")
|
||||
[[ $plugintarget ]] && munin disable $plugin
|
||||
mv ${plugins[1]}/$plugin ${plugins[0]}
|
||||
[[ $plugintarget ]] && munin enable $plugin
|
||||
fi
|
||||
}
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
munin_help() { # shows this
|
||||
grep '^munin_.*().*#' $(which $0) |
|
||||
sed 's/().*#/ : /;s/_/ /'
|
||||
}
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
munin_${1:-help}
|
||||
|
||||
# consider to generate a warning with absolute graph styles:
|
||||
# grep -i "\.type *absolute"
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue