#!/usr/bin/perl -w # # Plugin to monitor the percent of table space used on isam and myisam # tables on a mysql server. # # Parameters: # # config # autoconf # suggest # # Configuration variables # # mysqlopts - Options to pass to mysql # statefile - where to put the statefile # ignore - Tables to ignore. Regex. # absolute - use tables sizes, not percent of maximum # # $Log: mysql_isam_space_.in,v $ # Revision 1.1 2005/11/06 13:18:28 lupe # Initial revision # # Revision 1.2 2004/05/20 13:57:12 jimmyo # Set categories to some of the plugins. # # Revision 1.1 2004/01/02 18:50:00 jimmyo # Renamed occurrances of lrrd -> munin # # Revision 1.1.1.1 2004/01/02 15:18:07 jimmyo # Import of LRRD CVS tree after renaming to Munin # # Revision 1.15 2003/12/08 10:52:31 jimmyo # Bugfix when printing values # # Revision 1.14 2003/11/07 17:43:16 jimmyo # Cleanups and log entries # # # #%# family=auto #%# capabilities=suggest autoconf my $DB = `basename $0 | sed 's/^mysql_isam_space_//g' | tr '_' '-'` ; chomp $DB; my $STATEFILE = $ENV{'statefile'} || "/var/lib/munin/plugin-state/plugin-mysql_isam_space.state"; my $MYSQLSHOW = $ENV{'mysqlshow'} || 'mysqlshow'; my $ABSOLUTE = exists $ENV{'absolute'}; my @mysql_opts = (); if (exists $ENV{'mysqlopts'}) { @mysql_opts = split /\s+/, $ENV{'mysqlopts'}; } my $tables = undef; my $databses = undef; &print_autoconf () if ($ARGV[0] and $ARGV[0] eq "autoconf"); if (&use_statefile) { ($databases, $tables) = &read_statefile; } else { ($databases, $tables) = &fetch_state_from_mysql; } &print_config ($tables) if ($ARGV[0] and $ARGV[0] eq "config"); &print_suggest ($databases, $tables) if ($ARGV[0] and $ARGV[0] eq "suggest"); foreach my $t (keys %{$tables}) { printf ("%s.%s %f\n", $t, "value ", $tables->{$t}); } sub print_config { my $tables = shift; print "graph_title MySQL \"$DB\" isam/myisam table-space usage\n"; print "graph_args --base 1000\n"; print "graph_vlabel percent\n"; print "graph_category mysql\n"; foreach my $t (keys %{$tables}) { my $label = $t; if (length ($t) >= 20) { $label = sprintf ("...%17s", substr ($t, -17)); } print $t, ".label $label\n"; print $t, ".warning 0:90\n"; print $t, ".critical 0:95\n"; } exit 0; } sub read_statefile { my $tables = shift; my $databases = undef; # Read the statefile open (IN, $STATEFILE) or die "Could not open \"$STATEFILE\" for reading: $!"; while () { tr/זרו/eoa/; if (/^$DB\.([^\s]+)\s+([\d\.]+)\s*$/) { $tables->{$1} = $2; } if (/^([^\.]+)\./) { if (! grep (/^$1$/, @{$databases})) { push (@{$databases}, $1); } } } close (IN); return ($databases, $tables); } sub use_statefile { if (-f $STATEFILE) { if ((stat ($STATEFILE))[9] > (time - 3600)) { return 1; } } return 0; } sub fetch_state_from_mysql { my $tables = shift; my $databases = (); # Fork off mysqlshow my $pid = open (IN, '-|'); if (! defined ($pid)) { # Fork fail die "Couldn't fork."; } elsif ($pid == 0) { # Child exec ($MYSQLSHOW, @mysql_opts, "--status", "-v"); } my @mysql_status = ; close (IN); if ($? != 0) { exit 1; } foreach $line (@mysql_status) { $line =~ tr/זרו/eoa/; if ($line =~ /^\|\s+([^\|\s]+)\s+\|\s+([^\|\s]+)\s+\|/) { next if ($1 eq "Databases"); next if ($2 eq "N/A"); if ($2 > 0) { push (@{$databases}, $1) } } } if ((! -e $STATEFILE) or (-f $STATEFILE)) { &makedirfor ($STATEFILE); open (OUT, ">$STATEFILE") or die "Could not open \"$STATEFILE\" for writing: $!"; } else { die "Outfile exists and isn't a \"file\"."; } foreach my $db (@{$databases}) { # Fork off mysqlshow my $pid = open (IN, '-|'); if (! defined ($pid)) { # Fork fail die "Couldn't fork."; } elsif ($pid == 0) { # Child exec ($MYSQLSHOW, @mysql_opts, "--status", "-v", $db); # Notreached. } my %index; my $headerseen; while () { my @fields = split (/\s*\|\s*/); next if @fields > 2; # Separator line if (! $headerseen and $fields[1] eq "Name") { # Header line, grab field names %index = map {($fields[$_], $_)} 0..$#fields; } else { my $value = $ABSOLUTE ? $fields[$index{Data_length}] : (100*$fields[$index{Data_length}]/$fields[$index{Max_data_length}]); printf OUT ("%s.%s %f\n", $db, $fields[1], $value); $tables->{$fields[1]} = $value if $DB eq $db; } } close (IN); } close (OUT); return ($databases, $tables); } sub makedirfor { my $filename = shift; (my $dir = $filename) =~ s/\/[^\/]+$//; if ($dir ne $filename and ! -d $dir) { &makedirfor ($dir); mkdir ($dir, 0700); } return $dir; } sub print_suggest { my ($databases, $tables) = @_; foreach my $db (@{$databases}) { print "$db\n"; } exit 0; } sub print_autoconf { # First check that mysqlshow exists... if (! -x $MYSQLSHOW) { print "no (mysqlshow not found)\n"; exit 1; } # Fork off mysqlshow my $pid = open (IN, '-|'); if (! defined ($pid)) { # Fork fail die "Couldn't fork."; } elsif ($pid == 0) { # Child close STDERR; open (STDERR, ">&STDOUT"); exec ($MYSQLSHOW, @mysql_opts, "--status", "-v"); } my @slurp = ; close (IN); if ($? == 0) { print "yes\n"; exit 0; } elsif (grep (/Can't connect to local MySQL server/, @slurp)) { print "no (could not connect to mysql)\n"; } else { print "no\n"; } exit 1; } # vim:syntax=perl