mirror of
https://github.com/munin-monitoring/contrib.git
synced 2025-07-21 02:33:18 +00:00
when installing / first running the plugin, it can take longer than one munin-update call to create the $TIMEFILE. so until it is created we assume the $LOCKFILE is not too old yet and let the first run finish before we spawn additional processes.
201 lines
5.7 KiB
Perl
Executable file
201 lines
5.7 KiB
Perl
Executable file
#!/usr/bin/perl
|
|
# vim: set filetype=perl sw=4 tabstop=4 expandtab smartindent: #
|
|
|
|
=head1 NAME
|
|
|
|
du - Plugin to monitor multiple directories size
|
|
|
|
=head1 AUTHOR AND COPYRIGHT
|
|
|
|
Copyright 2011-2014 Luc Didry <luc AT didry.org>
|
|
Copyright 2022 Andreas Perhab, WT-IO-IT GmbH <a.perhab@wtioit.at>
|
|
|
|
=head1 HOWTO CONFIGURE AND USE :
|
|
|
|
=over
|
|
|
|
=item - /etc/munin/plugins/du
|
|
cp du /etc/munin/plugins/
|
|
|
|
=item - /etc/munin/plugin-conf.d/du_
|
|
|
|
[du]
|
|
user root
|
|
env.interval 20 # INTERVAL OF DU POLLING IN MINUTES
|
|
env.dirs /home/foo /home/bar # DIRECTORIES TO POLL
|
|
env.suppr /home/ # PLEASE USE \# INSTEAD OF #
|
|
timeout 900 # 15 MINUTES IN SECONDS
|
|
|
|
=item - restart Munin node
|
|
|
|
/etc/init.d/munin-node restart
|
|
|
|
=back
|
|
|
|
=head1 CREDITS
|
|
|
|
Based on the 'du_multidirs-v2' initially written in Bash by Christian Kujau <lists@nerdbynature.de> and modified by dano229.
|
|
This script was based on the 'homedirs' plugin, initially written in Perl by Philipp Gruber <pg@flupps.net>
|
|
|
|
=head1 MAGIC MARKERS
|
|
|
|
#%# family=auto
|
|
#%# capabilities=autoconf
|
|
|
|
=head1 LICENSE
|
|
|
|
This program 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, either version 3 of the License, or
|
|
any later version.
|
|
|
|
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, see <http://www.gnu.org/licenses/>.
|
|
|
|
=cut
|
|
|
|
use warnings;
|
|
use strict;
|
|
use Munin::Plugin;
|
|
use POSIX qw(setsid);
|
|
|
|
my $PLUGIN_NAME = "du";
|
|
my $CACHEFILE="$Munin::Plugin::pluginstatedir/du.cache";
|
|
my $TEMPFILE="$Munin::Plugin::pluginstatedir/du.tmp";
|
|
my $LOCKFILE="$Munin::Plugin::pluginstatedir/du.lock";
|
|
my $TIMEFILE="$Munin::Plugin::pluginstatedir/du.time";
|
|
|
|
##### autoconf
|
|
if( (defined $ARGV[0]) && ($ARGV[0] eq "autoconf") ) {
|
|
print "no\n";
|
|
## Done !
|
|
munin_exit_done();
|
|
}
|
|
|
|
## In the parent, it's just a regular munin plugin which reads a file with the infos
|
|
##### config
|
|
if( (defined $ARGV[0]) && ($ARGV[0] eq "config") ) {
|
|
print "graph_title Directory usage\n";
|
|
print "graph_args --base 1024 -l 1\n";
|
|
print "graph_vlabel Bytes\n";
|
|
print "graph_category disk\n";
|
|
print "graph_total total\n";
|
|
print "graph_info This graph shows the size of several directories\n";
|
|
|
|
my $foo = 0;
|
|
open (FILE, "<", $CACHEFILE) or munin_exit_fail();
|
|
while(defined (my $bar = <FILE>)) {
|
|
if ($bar =~ m/(\d+)\s+(.+)/) {
|
|
my $dir = $2;
|
|
clean_path(\$dir);
|
|
my $clean_dir = clean_fieldname($dir);
|
|
print "$clean_dir.label $dir\n";
|
|
if ($foo++) {
|
|
print "$clean_dir.draw STACK\n";
|
|
} else {
|
|
print "$clean_dir.draw AREA\n";
|
|
}
|
|
}
|
|
}
|
|
close(FILE);
|
|
## Done !
|
|
munin_exit_done();
|
|
}
|
|
|
|
##### fetch
|
|
if (open (FILE, "<", $CACHEFILE)) {
|
|
while(defined (my $foo = <FILE>)) {
|
|
if ($foo =~ m/(\d+)\s+(.+)/) {
|
|
my ($field, $value) = ($2, $1);
|
|
clean_path(\$field);
|
|
print clean_fieldname($field), ".value ", $value, "\n";
|
|
}
|
|
}
|
|
close(FILE);
|
|
}
|
|
daemonize();
|
|
|
|
#
|
|
##
|
|
### PUBLIC FUNCTIONS
|
|
###############################################################################
|
|
## Used to create the fork
|
|
sub daemonize {
|
|
chdir '/' or die "Can't chdir to /: $!";
|
|
defined(my $pid = fork) or die "Can't fork: $!";
|
|
munin_exit_done() if $pid;
|
|
open STDIN, '/dev/null' or die "Can't read /dev/null: $!";
|
|
open STDOUT, '>/dev/null' or die "Can't write to /dev/null: $!";
|
|
open STDERR, '>&STDOUT' or die "Can't dup stdout: $!";
|
|
setsid or die "Can't start a new session: $!";
|
|
## In the child, let's get the du infos if necessary
|
|
if (cache_is_too_old() && du_not_running()) {
|
|
my $dirs = $ENV{dirs};
|
|
system("touch $LOCKFILE; du -sb $dirs | sort -n -r > $TEMPFILE; cat $TEMPFILE > $CACHEFILE; rm $LOCKFILE; date +%s > $TIMEFILE;");
|
|
}
|
|
exit;
|
|
} ## daemonize
|
|
|
|
## Used to remove the beginning of the paths if wanted
|
|
sub clean_path {
|
|
my ($path) = @_;
|
|
if (defined $ENV{suppr}) {
|
|
my $pattern = $ENV{suppr};
|
|
$$path =~ s#^($pattern)##;
|
|
}
|
|
} ## clean_path
|
|
|
|
## Do you really need I told you what this functions are going to check ?
|
|
sub cache_is_too_old {
|
|
return 1 if (! -e $TIMEFILE);
|
|
my ($time) = `cat $TIMEFILE`;
|
|
chomp $time;
|
|
return 1 if ( (time - $time) > ($ENV{interval}*60) );
|
|
return 0;
|
|
} ## cache_is_too_old
|
|
|
|
sub du_not_running {
|
|
if (-e $LOCKFILE) {
|
|
if (-e $TIMEFILE) {
|
|
my ($time) = `cat $TIMEFILE`;
|
|
chomp $time;
|
|
if ( (time - $time) > ($ENV{interval}*60*60) ) {
|
|
# The cache is really old (60xinterval) => Maybe the lockfile wasn't properly deleted.
|
|
# Let's delete it.
|
|
unlink($LOCKFILE);
|
|
return 1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
} else {
|
|
# when $TIMEFILE is not yet created (first run is not yet finished), $LOCKFILE is honoured
|
|
# to prevent spawning multiple resource intensive processes
|
|
return 0;
|
|
}
|
|
} else {
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
sub munin_exit_done {
|
|
__munin_exit(0);
|
|
} ## sub munin_exit_done
|
|
|
|
sub munin_exit_fail {
|
|
__munin_exit(1);
|
|
} ## sub munin_exit_fail
|
|
|
|
#
|
|
##
|
|
### INTERNALS FUNCTIONS
|
|
###############################################################################
|
|
sub __munin_exit {
|
|
my $exitcode = shift;
|
|
exit($exitcode) if(defined $exitcode);
|
|
exit(1);
|
|
} ## sub __munin_exit
|