#!/usr/bin/perl -w

use strict;
use warnings;

use DBI ();
use Getopt::Long qw(GetOptions);
use noris::NetSaint;
use Safe ();

GetOptions(
    'command=s'     => \( my $Command    = 'SHOW STATUS' ),
    'data-source=s' => \( my $DataSource = 'DBI:mysql' ),
    'db-user=s'     => \my $DbUser,
    'db-password=s' => \my $DbPassword,
    'help|?' =>
      sub { exec perldoc => -F => $0 or die "exec('perldoc -F $0'): $!\n" },
    'status-db=s' => \my $StatusDb,
) or exit 1;

my $NetSaint = noris::NetSaint->new or die;

my %value_of;
{
    my $dbh =
      DBI->connect( $DataSource, $DbUser, $DbPassword, { RaiseError => 1 } );

    for ( @{ $dbh->selectall_arrayref($Command) } ) {
        ( my ( $variable, $value ) = @$_ ) == 2
          or die @$_ . 'Wert'
          . ( @$_ != 1 && 'e' )
          . " statt der erwarteten zwei: @$_\n";
        $value_of{$variable} = $value;
    }

    $dbh->disconnect;
}

dbmopen my %old_value_of, $StatusDb, 0600
  or die qq(Kann Status-DB "$StatusDb" nicht ffnen: $!\n)
  if defined $StatusDb;

for (@ARGV) {
    my $safe = Safe->new;
    while ( my ( $k, $v ) = each %value_of ) {
        ${ $safe->varglob($k) } = $v;
    }
    while ( my ( $k, $v ) = each %old_value_of ) {
        ${ $safe->varglob("_$k") } = $v;
    }
    my @result = $safe->reval($_);

    if ( length $@ ) {
        $NetSaint->update(
            Unknown => qq(Fehler beim Ausfhren der Regel "$_": $@) );
    }
    elsif (@result) {
        $NetSaint->update( @result > 1 ? shift @result : 'Unknown', "@result" );
        last;
    }
}

if ( defined $StatusDb ) {
    %old_value_of = %value_of;
    dbmclose %old_value_of
      or warn qq(Fehler beim Schlieen der Status-DB "$StatusDb": $!\n);
}

__END__

=head1 NAME

check_mysql_status - Status eines MySQL-Servers berwachen

=head1 SYNOPSE

    check_mysql_status
        -data-source "DBI:mysql:host=$host" \
        -db-user nagios \
        -status-db "$script:$host" \
        '
    my $diff_seconds = defined $_Uptime && $Uptime - $_Uptime
      or return;

    ( my $table_locks_waited_per_minute =
          ( $Table_locks_waited - $_Table_locks_waited ) /
          $diff_seconds * 60 );

    $table_locks_waited_per_minute < 1 ? 'OK' : 'Critical',
    sprintf "%.1f Table_locks_waited pro Minute",
            $table_locks_waited_per_minute
        '

=head1 BESCHREIBUNG

Dieses Nagios-kompatible Plugin fragt den Status eines MySQL-Servers ab.
Die ermittelten Werte knnen mittels Perl-Code, der in einer L<Safe>-Umgebung
luft, ausgewertet werden, dem sie dazu als gleichnamige (inkl. Erhaltung
der Gro-/Kleinschreibung) Skalarvariablen zur Verfgung gestellt werden,
also etwa C<$Table_locks_waited>.

Es knnen beliebig viele Perl-Codeschnipsel als Kommandozeilenargumente
angegeben werden.
Diese werden nacheinander durchlaufen, bis eines davon Rckgabewerte liefert.
Dabei wird eine Liste von zwei Werten erwartet: Das erste Element gibt den zu
setzenden Nagios-Status an, das zweite die zugehrige Statusmeldung.

Da Nagios Probleme mit bestimmten Sonderzeichen bei Plugin-Aufrufen hat, wird
empfohlen, dieses Plugin ber einen Wrapper aufzurufen.

=head1 OPTIONEN

=over 4

=item -command SQL-Kommando

zur Festlegung des SQL-Kommandos, das zur Statusabfrage an den Datenbankserver
gestellt wird;
Default: C<SHOW STATUS>

=item -status-db Dateiname

Name einer Datei, die dazu dient, die Werte des jeweils vorangegangenen
Plugin-Aufrufs zwischenzuspeichern.
Diese werden dann dem auf der Kommandozeile bergebenen Perl-Code in
Skalarvariablen bereitgestellt, deren Name jeweils ein Unterstrich vorangestellt
wird, also etwa C<$_Table_locks_waited>.
Damit ist es also etwa mglich, Deltas zum vorangegangenen Wert zu ermitteln.

=item -help

=item -?

um (nur) diese Dokumentation anzeigen zu lassen

=back

=head1 AUTOR

 Martin H. Sluka
 fr die noris network AG
 RT#398409

