Munin: diferència entre les revisions

De WikiMar
Salta a la navegació Salta a la cerca
Línia 128: Línia 128:


  yum install munin munin-nginx
  yum install munin munin-nginx
===Nginx_webserver===


Same steps for the Dynamic graphics as in the Ubuntu server
Same steps for the Dynamic graphics as in the Ubuntu server


Same steps for Nginx as in the Ubuntu server
Same steps for Nginx as in the Ubuntu server [[Munin#Nginx_webserver]]





Revisió del 12:10, 1 set 2016

Install Munin to the Ubuntu server

sudo apt-get install munin


Dynamic graphics

To be able to zoom in the graphics, edit /etc/munin/munin.conf and change:

html_strategy cgi
graph_strategy cgi

Nginx webserver

If using Nginx, add to your host config (ex. /etc/nginx/sites-enabled/default ):

        location /munin/static/ {
                alias /etc/munin/static/;
                expires modified +1w;
        }

#       location /munin {
#               # auth_basic            "Restricted";
#               # Create the htpasswd file with the htpasswd tool.
#               # auth_basic_user_file  /etc/nginx/htpasswd;
#
#               alias /var/cache/munin/www;
#               expires modified +310s;
#       }

        location /munin/ {
                fastcgi_split_path_info ^(/munin)(.*);
                fastcgi_param PATH_INFO $fastcgi_path_info;
                fastcgi_pass unix:/var/run/munin/fastcgi-html.sock;
                include fastcgi_params;
        }

        location ^~ /munin-cgi/munin-cgi-graph/ {
                fastcgi_split_path_info ^(/munin-cgi/munin-cgi-graph)(.*);
                fastcgi_param PATH_INFO $fastcgi_path_info;
                fastcgi_pass unix:/var/run/munin/fastcgi-graph.sock;
                include fastcgi_params;
        }


Create a new service file:

cat /etc/init.d/munin-fcgi-marti 
#!/bin/bash

### BEGIN INIT INFO
# Provides:          munin-fcgi
# Required-Start:    $remote_fs $syslog $network
# Required-Stop:     $remote_fs $syslog $network
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start munin FCGI processes at boot time
# Description:       Start the FCGI processes behind http://munin.*/
### END INIT INFO

graph_pidfile="/var/run/munin/fcgi_graph.pid"
# Ubuntu 12.10: /usr/lib/cgi-bin/munin-cgi-graph
graph_cgi="/usr/lib/munin/cgi/munin-cgi-graph"
html_pidfile="/var/run/munin/fcgi_html.pid"
# Ubuntu 12.10: /usr/lib/cgi-bin/munin-cgi-html
html_cgi="/usr/lib/munin/cgi/munin-cgi-html"

retval=0

. /lib/lsb/init-functions

start() {
  chown munin:munin /var/log/munin/*
  echo -n "Starting munin graph FastCGI: "
  start_daemon -p ${graph_pidfile} /usr/bin/spawn-fcgi -u munin -g munin \
      -s /var/run/munin/fastcgi-graph.sock -U www-data ${graph_cgi}
  echo
  echo -n "Starting munin html FastCGI: "
  start_daemon -p ${html_pidfile} /usr/bin/spawn-fcgi -u munin -g munin \
      -s /var/run/munin/fastcgi-html.sock -U www-data ${html_cgi}
  echo
  retval=$?
}
stop() {
  echo -n "Stopping munin graph FastCGI: "
  killproc -p ${graph_pidfile} ${graph_cgi} -QUIT
  echo
  echo -n "Stopping munin html FastCGI: "
  killproc -p ${html_pidfile} ${html_cgi} -QUIT
  echo
  retval=$?
  rm /var/run/munin/fastcgi-graph.sock
  rm /var/run/munin/fastcgi-html.sock
}

case "$1" in
  start)
    start
  ;;
  stop)
    stop
  ;;
  restart)
    stop
    start
  ;;
  *)
    echo "Usage: munin-fcgi {start|stop|restart}"
    exit 1
  ;;
esac
exit $retval


Start it:

service  munin-fcgi-marti restart

Add it to autostart:

update-rc.d munin-fcgi-marti defaults



Install Munin to the Fedora/Centos server

yum install munin munin-nginx


Nginx_webserver

Same steps for the Dynamic graphics as in the Ubuntu server

Same steps for Nginx as in the Ubuntu server Munin#Nginx_webserver


Create a new service file: /etc/init.d/munin-fcgi-marti2

#!/bin/sh
### BEGIN INIT INFO
# Provides:          munin-fcgi-marti2
# Required-Start:    $remote_fs $network
# Required-Stop:     $remote_fs $network
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: starts munin-fastcgi
# Description:       Spawn Munin FCGI sockets for Web access
### END INIT INFO

#
# munin-fastcgi     Startup script for Munin CGI services
#
# chkconfig: - 84 15
# description: Loading Munin CGI services using spawn-cgi
#              HTML files and CGI.
#
# Author:  Ryan Norbauer 
# Modified:     Geoffrey Grosenbach http://topfunky.com
# Modified:     David Krmpotic http://davidhq.com
# Modified:     Kun Xi http://kunxi.org
# Modified:     http://drumcoder.co.uk/
# Modified:     http://uname.pingveno.net/
# Modified:     the_architecht http://iwbyt.com/
PATH=/usr/local/bin/:/usr/local/sbin:$PATH
DAEMON=$(which spawn-fcgi)
FCGI_GRAPH_SOCK=/var/run/munin/fcgi-graph.sock
FCGI_HTML_SOCK=/var/run/munin/fcgi-html.sock
WWW_USER=nginx
FCGI_USER=munin
FCGI_GROUP=munin
FCGI_SPAWN_GRAPH=/var/www/cgi-bin/munin-cgi-graph
FCGI_SPAWN_HTML=/var/www/cgi-bin/munin-cgi-html
PIDFILE_GRAPH=/var/run/munin/fastcgi-munin-graph.pid
PIDFILE_HTML=/var/run/munin/fastcgi-munin-html.pid
DESC="Munin FCGI for Graph and HTML"

# Gracefully exit if the package has been removed.
test -x $DAEMON || exit 0
test -x $FCGI_SPAWN_GRAPH || exit 0
test -x $FCGI_SPAWN_HTML || exit 0

start() {
  $DAEMON -s $FCGI_GRAPH_SOCK -U $WWW_USER -u $FCGI_USER -g $FCGI_GROUP -P $PIDFILE_GRAPH $FCGI_SPAWN_GRAPH 2> /dev/null || echo "Graph Already running"
  $DAEMON -s $FCGI_HTML_SOCK  -U $WWW_USER -u $FCGI_USER -g $FCGI_GROUP -P $PIDFILE_HTML $FCGI_SPAWN_HTML 2> /dev/null || echo "HTML Already running"
}

stop() {
  kill -QUIT `cat $PIDFILE_GRAPH` || echo "Graph not running"
  kill -QUIT `cat $PIDFILE_HTML` || echo "HTML Not running"
}

restart() {
  kill -HUP `cat $PIDFILE_GRAPH` || echo "Can't reload Graph"
  kill -HUP `cat $PIDFILE_HTML` || echo "Can't reload HTML"
}

case "$1" in
  start)
    echo "Starting $DESC: "
    start
  ;;
  stop)
    echo "Stopping $DESC: "
    stop
  ;;
  restart|reload)
    echo "Restarting $DESC: "
    stop
    # One second might not be time enough for a daemon to stop,
    # if this happens, d_start will fail (and dpkg will break if
    # the package is being upgraded). Change the timeout if needed
    # be, or change d_stop to have start-stop-daemon use --retry.
    # Notice that using --retry slows down the shutdown process somewhat.
    sleep 1
    start
  ;;
  *)
    echo "Usage: $SCRIPTNAME {start|stop|restart|reload}" >&2
    exit 3
  ;;
esac

exit $?



Start it:

service  munin-fcgi-marti2 restart
or
systemctl restart munin-fcgi-marti2


Add it to autostart:

systemctl enable munin-fcgi-marti2

Install Munin to a client

First you need to install munin client package using the following commands

   sudo apt-get install munin-node

Now you need to edit the munin-node.conf file to specify that your monitoring server is allowed to poll the client for information.

   sudo vi /etc/munin/munin-node.conf

Search for the section that has the line "allow ^127\.0\.0\.1$". Modify the IP address to reflect your monitoring server's IP address.If your server ip is 172.30.2.100

   allow ^\.172\.30\.2\.100$

Save and exit the file

You need to restart the munin client using the following information

   sudo service munin-node restart

Now you need to login in to your munin server and edit the munin.conf file

   sudo vi /etc/munin/munin.conf

Copy the following section and change the ip address to your remote server client ip address

   [MuninMonitor]
   address 127.0.0.1
   use_node_name yes

to

   [MuninMonitor]
   address 172.30.2.101
   use_node_name yes

Finall you need to restart the apache server using the following command

   sudo service apache2 restart


Add variables

/usr/sbin/munin-node-configure --suggest
/usr/sbin/munin-node-configure --shell | sh
/etc/init.d/munin-node restart


Additional Plugins

The munin-plugins-extra package contains performance checks additional services such as DNS, DHCP, Samba, etc. To install the package run the following command from the terminal

   sudo apt-get install munin-plugins-extra

Make sure you have install this package on both the server and node machines.


Info from: http://www.ubuntugeek.com/install-munin-monitoring-tool-on-ubuntu-14-04-server.html


Other plugins added manually

Add SNMP Routers and Printers

dd-wrt allows SNMP to be enabled under the Services menu.

If you're connecting using OpenVPN you need to open the UPD port 161 in the firewall (Administration tab / firewall commands):

iptables -I INPUT 1 -p udp --dport 161 -j ACCEPT 

Then you add it to one machine working as munin-node:

munin-node-configure --shell --snmp 192.168.100.250
munin-node-configure --shell --snmp 192.168.100.250 |/bin/sh


More info: http://munin-monitoring.org/wiki/Using_SNMP_plugins

multi_tcp_ping - TCP ping plugin

Downloaded from: http://gallery.munin-monitoring.org/contrib/plugins/network/multi_tcp_ping or http://munin-monitoring.org/browser/munin-contrib/plugins/network/multi_tcp_ping


/etc/munin/plugins/multi_tcp_ping

#!/usr/bin/perl

=head1 NAME

multi_tcp_ping - Graphs together the TCP ping results for several hosts

=head1 SYNOPSIS

This plugin is meant to be called from Munin. You should set the
'hosts' environment variable from Munin's configuration (i.e.
/etc/munin/munin.conf) to specify which hosts and ports to query.

=head1 DESCRIPTION

This plugin expects to receive the following environment variables:

=over 4

=item hosts (REQUIRED!)

Comma-separated list of hosts to query. You can specify the TCP port
to connect to on each of the hosts by listing them as host:port - The
port defaults to 80. The following is a valid hosts declaration:

    hosts='192.168.0.15, 192.168.0.18:22'

It will query host 192.168.0.15 on the default port (80), as well as
host 192.168.0.18 on port 22.

=back

If the connection was opened successfully, it gives as the return
value the time it took to establish the connection. If the requested
host is not reachable, a hard-wired '-0.01' will be returned. Why
-0.01? Because giving a negative value is the best way to easily get
-visually- that something failed. Connection establishment times are
usually in the 5-500ms range. 100ms will be not too little (and thus
invisible), not too much (and thus killing the details in our graphs).

=head1 DEPENDS ON

L<Net::Ping>

=head1 SEE ALSO

L<munin>, L<munin-node>

=head1 AUTHOR

Gunnar Wolf <[email protected]>

=head1 COPYRIGHT


Copyright 2008 Gunnar Wolf, Instituto de Investigaciones
Economicas, UNAM. This plugin is Free Software; you can
redistribute it and/or modify it under the terms of the GNU General
Public License as published by the Free Software Foundation; version 2
dated June, 1991, or any later version (at your choice).

This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
USA.

=cut

use strict;
use warnings;

# This evil "eval" is to make Travis CI able to test the plugin syntax
# without having a perl built with threads.
#
# Also: The use of interpreter-based threads in perl is officially
# discouraged.
eval 'use threads; 1;' or die 'Could not use threads';

use Net::Ping;
my (%defaults, @hosts, $cmd_arg);

%defaults = (port => 80, timeout => 2, unreachable => -0.01);
@hosts = get_hosts($ENV{hosts});
die "Hosts not set - cannot continue\n" unless @hosts;

$cmd_arg = $ARGV[0] || '';
config() if($cmd_arg eq "config");
autoconf() if ($cmd_arg eq 'autoconf');

for my $host (@hosts) { 
    threads->new(\&ping_host, $host)
}

map {$_->join} threads->list;
exit 0;

sub ping_host {
    my ($host, $addr, $p, $ret, $time, $ip);
    $host = shift;
    $addr = host_label_for($host);

    $p=Net::Ping->new("tcp", $defaults{timeout});
    $p->hires();
    $p->{port_num} = $host->[1] || $defaults{port};

    ($ret, $time, $ip) = $p->ping($host->[0]);

    $time = $defaults{unreachable} if !$ret;
    print "${addr}.value $time\n";
}

sub get_hosts {
    # Hosts are defined in the 'hosts' environment variable. It's a list of
    # hosts (and optionally ports) - We parse the list and arrange it neatly
    # to be easily consumed.
    my ($hostsdef, @hosts);
    $hostsdef = shift;
    return unless $hostsdef;

    for my $host (split(/,/, $hostsdef)) {
	$host =~ s/\s//g;

	$host =~ /^(?:([^:]+))
	    (?::(\d+))?$/x;

	push @hosts, [$1, $2 || $defaults{port}];

    }

    return @hosts;
}

sub config {
    my @res = ("graph_title TCP connection times",
	       "graph_args --base 1000 -l 0",
	       "graph_vlabel seconds",
	       "graph_category network",
	       "graph_info Shows the time to establish a TCP connection");
    for my $host (@hosts) {
	my $addr = host_label_for($host);
	push @res, "$addr.label $addr";
	push @res, "$addr.draw LINE2";
	push @res, "$addr.info Time to establish TCP connection to " .
	    "$host->[0]:$host->[1]";

    }

    print map {"$_\n"} @res;
    exit 0;
}

sub autoconf {
    print "yes\n";
    exit 0;
}

sub host_label_for {
    my ($ip, $port) = @{$_[0]};
    # Periods and colonsare not allowed in variable names
    my $addr = "src_${ip}_${port}";
    $addr =~ s/\./_/g;
    return $addr;
}


And put it to:

sudo vi /etc/munin/plugins/multi_tcp_ping
sudo chmod +x /etc/munin/plugins/multi_tcp_ping

Add the hosts to the following new file:

sudo vi /etc/munin/plugin-conf.d/multi_tcp_ping

or at the end of:

sudo vi /etc/munin/plugin-conf.d/munin-node
[multi_tcp_ping]
env.hosts 192.168.1.2, google.com, 192.168.100.1, 192.168.100.2, 192.168.100.100:3389, 192.168.101.1


Restart munin-node

service munin-node restart


Old system with a dedicated hosts file

(the ports specified in the file do not work yet, so only 80 is working)

From: https://forum.xakep.ru/topic/1398094/

Create file /usr/share/munin-marti/tcp_multi_ping'

cat tcp_multi_ping
#!/usr/bin/perl

=head1 NAME

multi_tcp_ping - Graphs together the TCP ping results for several hosts

=head1 SYNOPSIS

This plugin is meant to be called from Munin. You should set the
'hosts' environment variable from Munin's configuration (i.e.
/etc/munin/munin.conf) to specify which hosts and ports to query.

=head1 DESCRIPTION

This plugin expects to receive the following environment variables:

=over 4

=item hosts (REQUIRED!)

Comma-separated list of hosts to query. You can specify the TCP port
to connect to on each of the hosts by listing them as host:port - The
port defaults to 80. The following is a valid hosts declaration:

    hosts='192.168.0.15, 192.168.0.18:22'

It will query host 192.168.0.15 on the default port (80), as well as
host 192.168.0.18 on port 22.

=back

If the connection was opened successfully, it gives as the return
value the time it took to establish the connection. If the requested
host is not reachable, a hard-wired '-0.01' will be returned. Why
-0.01? Because giving a negative value is the best way to easily get
-visually- that something failed. Connection establishment times are
usually in the 5-500ms range. 100ms will be not too little (and thus
invisible), not too much (and thus killing the details in our graphs).

=head1 DEPENDS ON

L<Net::Ping>

=head1 SEE ALSO

L<munin>, L<munin-node>

=head1 AUTHOR

Gunnar Wolf <[email protected]>

=head1 COPYRIGHT


Copyright 2008 Gunnar Wolf, Instituto de Investigaciones
Economicas, UNAM. This plugin is Free Software; you can
redistribute it and/or modify it under the terms of the GNU General
Public License as published by the Free Software Foundation; version 2
dated June, 1991, or any later version (at your choice).

This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
USA.

=cut

use strict;
use warnings;

# This evil "eval" is to make Travis CI able to test the plugin syntax
# without having a perl built with threads.
#
# Also: The use of interpreter-based threads in perl is officially
# discouraged.
eval 'use threads; 1;' or die 'Could not use threads';

use Net::Ping;
my (%defaults, @hosts, $cmd_arg, $config_file_name);
%defaults = (port => 80, timeout => 2, unreachable => -0.01);

#$config_file_name = "/usr/share/munin/plugins/hostslist.ip";
$config_file_name = "/usr/share/munin-marti/tcp_multi_ping.ip";



open (IN_FILE,"<$config_file_name") or die "Unable to open file hostslist.ip";
while (<IN_FILE>){
# if (/\d+\.\d+\.\d+\.\d+/){
s/\s//g; push (@hosts,[$_,$defaults{port}]);
# }
}

# @hosts = get_hosts($ENV{hosts});


die "Hosts not set - cannot continue\n" unless @hosts;

$cmd_arg = $ARGV[0] || '';
config() if($cmd_arg eq "config");
autoconf() if ($cmd_arg eq 'autoconf');

for my $host (@hosts) { 
    threads->new(\&ping_host, $host)
}

map {$_->join} threads->list;
exit 0;

sub ping_host {
    my ($host, $addr, $p, $ret, $time, $ip);
    $host = shift;
    $addr = host_label_for($host);

    $p=Net::Ping->new("tcp", $defaults{timeout});
    $p->hires();
    $p->{port_num} = $host->[1] || $defaults{port};

    ($ret, $time, $ip) = $p->ping($host->[0]);

    $time = $defaults{unreachable} if !$ret;
    print "${addr}.value $time\n";
}

sub get_hosts {
    # Hosts are defined in the 'hosts' environment variable. It's a list of
    # hosts (and optionally ports) - We parse the list and arrange it neatly
    # to be easily consumed.
    my ($hostsdef, @hosts);
    $hostsdef = shift;
    return unless $hostsdef;

    for my $host (split(/,/, $hostsdef)) {
        $host =~ s/\s//g;

        $host =~ /^(?:([^:]+))
            (?::(\d+))?$/x;

        push @hosts, [$1, $2 || $defaults{port}];

    }

    return @hosts;
}

sub config {
    my @res = ("graph_title TCP connection times",
               "graph_args --base 1000 -l 0",
               "graph_vlabel seconds",
               "graph_category network",
               "graph_info Shows the time to establish a TCP connection");
    for my $host (@hosts) {
        my $addr = host_label_for($host);
        push @res, "$addr.label $addr";
        push @res, "$addr.draw LINE2";
        push @res, "$addr.info Time to establish TCP connection to " .
            "$host->[0]:$host->[1]";

    }

    print map {"$_\n"} @res;
    exit 0;
}

sub autoconf {
    print "yes\n";
    exit 0;
}

sub host_label_for {
    my ($ip, $port) = @{$_[0]};
    # Periods and colonsare not allowed in variable names
    my $addr = "src_${ip}_${port}";
    $addr =~ s/\./_/g;
    return $addr;
}


Put all your hosts to /usr/share/munin-marti/tcp_multi_ping.ip

google.com
hostssh.com:22

Create link:

sudo ln -s '/usr/share/munin-marti/tcp_multi_ping' '/etc/munin/plugins/tcp_multi_ping'


Restart munin-node

Apt Ubuntu

sudo vi /etc/munin/plugins/apt_ubuntu

From: https://raw.githubusercontent.com/munin-monitoring/contrib/master/plugins/ubuntu/apt_ubuntu

#!/usr/bin/env python
# -*- encoding: iso-8859-1 -*-
#
# apt_ubuntu
#
# Plugin to monitor packages that should be installed on Ubuntu systems.
#
# Author: Stefan Daniel Schwarz <[email protected]>
#
# v1.0 2008-11-07 - First draft
# v1.1 2008-11-08 - critical = #: First # critical, rest warning
# v1.2 2008-11-09 - Code cleanup for MuninExchange submission
#
# Usage: place in /etc/munin/plugins/ (or link it there using ln -s)
#
# Parameters understood:
#
#       config   (required)
#       autoconf (optional - used by munin-config)
#
# Magic markers - optional - used by installation scripts and
# munin-config:
#
#%# capabilities=autoconf
#%# family=contrib

###########################################################
category = 'security' # 'upgrades'
title = 'Upgradable packages' # 'Upgradeable packages'
vlabel = 'Total packages'
other = 'other'
total = 'total'

archives = ['security', 'updates', 'proposed', 'backports']
colour = ['ff0000', '22ff22', '0022ff', '00aaaa', 'ff00ff']
origins = ['Ubuntu']

critical = 1
###########################################################

import os
import sys
import warnings

warnings.filterwarnings('ignore', 'apt API not stable yet', FutureWarning)

def autoconf():
    if os.path.exists('/etc/lsb-release'):
        for line in open('/etc/lsb-release'):
            if line.strip() == 'DISTRIB_ID=Ubuntu':
                try:
                    import apt
                except ImportError:
                    print 'no (python-apt not installed)'
                    sys.exit(1)
                cache = apt.Cache()
                if not cache.has_key('update-notifier-common'):
                    print 'no (update-notifier-common not found)'
                    sys.exit(1)
                if not cache['update-notifier-common'].isInstalled:
                    print 'no (update-notifier-common not installed)'
                    sys.exit(1)
                if not os.path.exists('/etc/apt/apt.conf.d/10periodic'):
                    print 'no (/etc/apt/apt.conf.d/10periodic not found)'
                    sys.exit(1)
                for line in open('/etc/apt/apt.conf.d/10periodic'):
                    if line.strip() == 'APT::Periodic::Update-Package-Lists "1";':
                        print 'yes'
                        sys.exit(0)
                print 'no (APT::Periodic::Update-Package-Lists not "1")'
                sys.exit(1)
    print 'no'
    sys.exit(1)

def config():
    print 'graph_category security'
    print 'graph_title %s' % (title)
    #print 'graph_total %s' % (total)
    print 'graph_vlabel %s' % (vlabel)
    for i, archive in enumerate(archives + [other]):
        if len(colour) > i:
            print '%s.colour %s' % (archive, colour[i])
        if i < critical:
            print '%s.critical 0:0' % (archive)
        if i == 0:
            print '%s.draw AREA' % (archive)
        else:
            print '%s.draw STACK' % (archive)
        print '%s.label %s' % (archive, archive)
        if i + 1 > critical:
            print '%s.warning 0:0' % (archive)
    print 'total.colour 000000'
    print 'total.draw LINE1'
    print 'total.label %s' % (total)
    sys.exit(0)

def check_origin(pkg):
    #print 'Checking: %s (%s)' % (pkg.name, map(str, pkg.candidateOrigin))
    if pkg.candidate.origins:
        for archive in archives:
            for origin in pkg.candidate.origins:
                #a = origin.archive.rpartition('-')[2]
                a = origin.archive.split('-')[origin.archive.count('-')]
                if a == archive and origin.origin in origins:
                    return a
    return other

if len(sys.argv) > 1:
    if sys.argv[1] == 'autoconf':
        autoconf()
    elif sys.argv[1] == 'config':
        config()
    elif sys.argv[1]:
        print('unknown argument "' + sys.argv[1] + '"')
        sys.exit(1)

try:
    import apt
except ImportError:
    print "The module 'apt' is currently not installed.  You can install it by typing:\nsudo apt-get install python-apt\nImportError: No module named apt"
    sys.exit(1)

pkgs = {}
total = 0
for pkg in apt.Cache():
    if pkg.is_upgradable:
        a = check_origin(pkg)
        pkgs[a] = pkgs.get(a, 0) + 1
        total += 1

for archive in archives + [other]:
    print '%s.value %s' % (archive, pkgs.pop(archive, 0))

print 'total.value %s' % (total)

chmod +x /etc/munin/plugins/apt_ubuntu

Restart munin-node



multi_icmp_ping

/etc/munin/plugin-conf.d/multi_icmp_ping

[multi_icmp_ping]
user root
env.hosts 10.0.0.15, 10.0.0.16


/etc/munin/plugins/multi_icmp_ping

#!/usr/bin/perl

=head1 NAME

multi_icmp_ping - Graphs together the ICMP ping results for several hosts

=head1 SYNOPSIS

This plugin is meant to be called from Munin. You should set the
'hosts' environment variable from Munin's configuration (i.e.
/etc/munin/munin.conf) to specify which hosts and ports to query.

=head1 DESCRIPTION

This plugin expects to receive the following environment variables:

=over 4

=item hosts (REQUIRED!)

Comma-separated list of hosts to query. The following is a valid hosts declaration:

    hosts='192.168.0.15, 192.168.0.18'


=back

If the connection was opened successfully, it gives as the return
value the time it took to establish the connection. If the requested
host is not reachable, a hard-wired '-0.01' will be returned. Why
-0.01? Because giving a negative value is the best way to easily get
-visually- that something failed. Connection establishment times are
usually in the 5-500ms range. 100ms will be not too little (and thus
invisible), not too much (and thus killing the details in our graphs).

=head1 DEPENDS ON

L<Net::Ping>

=head1 SEE ALSO

L<munin>, L<munin-node>

=head1 AUTHOR

M Minoves

=head1 COPYRIGHT


This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
USA.

=cut

use strict;
use warnings;

# This evil "eval" is to make Travis CI able to test the plugin syntax
# without having a perl built with threads.
#
# Also: The use of interpreter-based threads in perl is officially
# discouraged.
eval 'use threads; 1;' or die 'Could not use threads';

use Net::Ping;
my (%defaults, @hosts, $cmd_arg);

%defaults = (port => 80, timeout => 2, unreachable => -0.01);
@hosts = get_hosts($ENV{hosts});
die "Hosts not set - cannot continue\n" unless @hosts;

$cmd_arg = $ARGV[0] || '';
config() if($cmd_arg eq "config");
autoconf() if ($cmd_arg eq 'autoconf');

for my $host (@hosts) { 
    threads->new(\&ping_host, $host)
}

map {$_->join} threads->list;
exit 0;

sub ping_host {
    my ($host, $addr, $p, $ret, $time, $ip);
    $host = shift;
    $addr = host_label_for($host);

    $p=Net::Ping->new("icmp", $defaults{timeout});
    $p->hires();
    #$p->{port_num} = $host->[1] || $defaults{port};

    ($ret, $time, $ip) = $p->ping($host->[0]);

    $time = $defaults{unreachable} if !$ret;
    print "${addr}.value $time\n";
}

sub get_hosts {
    # Hosts are defined in the 'hosts' environment variable. It's a list of
    # hosts (and optionally ports) - We parse the list and arrange it neatly
    # to be easily consumed.
    my ($hostsdef, @hosts);
    $hostsdef = shift;
    return unless $hostsdef;

    for my $host (split(/,/, $hostsdef)) {
	$host =~ s/\s//g;

	$host =~ /^(?:([^:]+))
	    (?::(\d+))?$/x;

	push @hosts, [$1, $2 || $defaults{port}];

    }

    return @hosts;
}

sub config {
    my @res = ("graph_title ICMP connection times",
	       "graph_args --base 1000 -l 0",
	       "graph_vlabel seconds",
	       "graph_category network",
	       "graph_info Shows the time to respond to an ICMP ping");
    for my $host (@hosts) {
	my $addr = host_label_for($host);
	push @res, "$addr.label $addr";
	push @res, "$addr.draw LINE2";
	push @res, "$addr.info Time to respond to an ICMP ping to " .
	    "$host->[0]:$host->[1]";

    }

    print map {"$_\n"} @res;
    exit 0;
}

sub autoconf {
    print "yes\n";
    exit 0;
}

sub host_label_for {
    my ($ip, $port) = @{$_[0]};
    # Periods and colonsare not allowed in variable names
    #my $addr = "src_${ip}_${port}";
    my $addr = "src_${ip}";
    $addr =~ s/\./_/g;
    return $addr;
}



multi_ssh_ping

/etc/munin/plugin-conf.d/multi_ssh_ping

[multi_ssh_ping]
env.hosts [email protected]:9.9.9.9, [email protected]:9.9.9.10
env.sshcommand sshpass -p password ssh -o StrictHostKeyChecking=no
env.pingcommand ping -A -w 2 -c 5


/etc/munin/plugins/multi_ssh_ping

#!/usr/bin/perl

=head1 NAME

multi_ssh_ping - Graphs together the pings mesured from a another host connecting using SSH

=head1 SYNOPSIS

This plugin is meant to be called from Munin. You should set the
'hosts' environment variable from Munin's configuration (i.e.
/etc/munin/munin.conf) to specify which hosts and ports to query.

=head1 DESCRIPTION

This plugin expects to receive the following environment variables:

=over 4

=item hosts (REQUIRED!)

Comma-separated list of sshhost:pinghosts to query. It connects to sshhost using ssh and from there it pings pinghost. The following is a valid hosts declaration:

	hosts='[email protected]:192.168.0.17, [email protected]:192.168.0.18'

=item sshcommand (REQUIRED!)

The ssh command to use before each of the hosts above

	sshcommand='sshpass -p password ssh -o StrictHostKeyChecking=no'

=item pingcommand (REQUIRED!)

The ping command to use after each of the hosts above

        pingcommand='ping -c 2 -w 1'


=back

If the connection was opened successfully, it gives as the return
value the time it took to establish the connection. If the requested
host is not reachable, a hard-wired '-0.01' will be returned. Why
-0.01? Because giving a negative value is the best way to easily get
-visually- that something failed. Connection establishment times are
usually in the 5-500ms range. 100ms will be not too little (and thus
invisible), not too much (and thus killing the details in our graphs).

=head1 DEPENDS ON

L<Net::Ping>

=head1 SEE ALSO

L<munin>, L<munin-node>

=head1 AUTHOR

Minoves

=head1 COPYRIGHT


This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
USA.

=cut

use strict;
use warnings;

# This evil "eval" is to make Travis CI able to test the plugin syntax
# without having a perl built with threads.
#
# Also: The use of interpreter-based threads in perl is officially
# discouraged.
eval 'use threads; 1;' or die 'Could not use threads';

#use Net::Ping;
my (%defaults, @hosts, $cmd_arg, $pingcommand, $sshcommand);

%defaults = (unreachable => -0.01);
@hosts = get_hosts($ENV{hosts});
die "hosts not set - cannot continue\n" unless @hosts;


$sshcommand = $ENV{sshcommand};
die "sshcommand not set - cannot continue\n" unless $sshcommand;

$pingcommand = $ENV{pingcommand};
die "pingcommand not set - cannot continue\n" unless $pingcommand;


$cmd_arg = $ARGV[0] || '';
config() if($cmd_arg eq "config");
autoconf() if ($cmd_arg eq 'autoconf');

for my $host (@hosts) { 
    threads->new(\&ping_host, $host)
}

map {$_->join} threads->list;
exit 0;

sub ping_host {
    my ($host, $addr, $p, $ret, $time, $ip);
    $host = shift;
    $addr = host_label_for($host);
    
        my $execcommand = $sshcommand . ' ' . $host->[0]  . ' ' . $pingcommand . ' ' . $host->[1];
	my @ping = `$execcommand`;
	chomp @ping;
	my $ping = join(" ", @ping);
	#my $ping_time = "U";
	#my $packet_loss = "U";
	
	my $ping_time = $defaults{unreachable};
	$ping_time = ($1 / 1000) if ($ping =~ m@min/avg/max.*\s\d+(?:\.\d+)?/(\d+(?:\.\d+)?)/\d+(?:\.\d+)?@);
	# $packet_loss = $1 if ($ping =~ /(\d+)% packet loss/);
	print "${addr}.value ".  $ping_time . "\n";

}

sub get_hosts {
    # Hosts are defined in the 'hosts' environment variable. 
    my ($hostsdef, @hosts);
    $hostsdef = shift;
    return unless $hostsdef;

    for my $host (split(/,/, $hostsdef)) {
	$host =~ s/\s//g;

	$host =~ /^(?:([^:]+))
	    (?::(.+))?$/x;

	push @hosts, [$1, $2];

    }

    return @hosts;
}

sub config {
    my @res = ("graph_title SSH ping delay times",
	       "graph_args --base 1000 -l 0",
	       "graph_vlabel seconds",
	       "graph_category network",
	       "graph_info Shows the time to respond to an ICMP ping from a SSH host");
    for my $host (@hosts) {
	my $addr = host_label_for($host);
	push @res, "$addr.label $addr";
	push @res, "$addr.draw LINE2";
	push @res, "$addr.info ICMP ping time from " .
	    "$host->[0]" . " to " . "$host->[1]";

    }

    print map {"$_\n"} @res;
    exit 0;
}

sub autoconf {
    print "yes\n";
    exit 0;
}

sub host_label_for {
    my ($ssh, $host) = @{$_[0]};
    # Periods and colonsare not allowed in variable names
    $ssh =~ s/.*\@//g;
    my $addr = "src_${ssh}__${host}";
    $addr =~ s/\./_/g;
    return $addr;
}