From 080aa66d1be2ef439243d4a86e77edb985bf7f0c Mon Sep 17 00:00:00 2001 From: Greg Sabino Mullane Date: Sun, 15 Feb 2009 11:16:35 -0500 Subject: [PATCH] Add disabled_triggers check. Redo multi-version run_command() bit. --- check_postgres.pl | 154 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 130 insertions(+), 24 deletions(-) diff --git a/check_postgres.pl b/check_postgres.pl index 26bc25fe2..0d5d431b4 100755 --- a/check_postgres.pl +++ b/check_postgres.pl @@ -28,7 +28,7 @@ $Data::Dumper::Varname = 'POSTGRES'; $Data::Dumper::Indent = 2; $Data::Dumper::Useqq = 1; -our $VERSION = '2.7.3'; +our $VERSION = '2.8.0'; use vars qw/ %opt $PSQL $res $COM $SQL $db /; @@ -203,6 +203,7 @@ our $action_info = { custom_query => [0, 'Run a custom query.'], database_size => [0, 'Report if a database is too big.'], dbstats => [1, 'Returns stats from pg_stat_database: Cacti output only'], + disabled_triggers => [0, 'Check if any triggers are disabled'], disk_space => [1, 'Checks space of local disks Postgres is using.'], fsm_pages => [1, 'Checks percentage of pages used in free space map.'], fsm_relations => [1, 'Checks percentage of relations used in free space map.'], @@ -743,6 +744,9 @@ show_dbstats() if $action eq 'dbstats'; ## Check how long since the last checkpoint check_checkpoint() if $action eq 'checkpoint'; +## Check how long since the last checkpoint +check_disabled_triggers() if $action eq 'disabled_triggers'; + finishup(); exit 0; @@ -1057,8 +1061,33 @@ sub run_command { ## If we've got different SQL, use this first run to simply grab the version ## Then we'll use that info to pick the real query if ($arg->{version}) { - $arg->{oldstring} = $string; - $string = 'SELECT version()'; + if (!$db->{version}) { + $arg->{versiononly} = 1; + $arg->{oldstring} = $string; + $string = 'SELECT version()'; + } + else { + $string = $arg->{oldstring} || $arg->{string}; + for my $row (@{$arg->{version}}) { + if ($row !~ s/^([<>]?)(\d+\.\d+)\s+//) { + ndie "Invalid version string: $row"; + } + my ($mod,$ver) = ($1||'',$2); + if ($mod eq '>' and $db->{version} > $ver) { + $string = $row; + last; + } + if ($mod eq '<' and $db->{version} < $ver) { + $string = $row; + last; + } + if ($mod eq '' and $db->{version} eq $ver) { + $string = $row; + } + } + delete $arg->{version}; + $info->{command} = $string; + } } push @args, '-c', $string; @@ -1132,6 +1161,23 @@ sub run_command { ## Allow an empty query (no matching rows) if requested if ($arg->{emptyok} and $db->{slurp} =~ /^\s*$/o) { } + + ## If we just want a version, grab it and redo + if ($arg->{versiononly}) { + if ($db->{error}) { + ndie $db->{error}; + } + if ($db->{slurp} !~ /PostgreSQL (\d+\.\d+)/) { + ndie qq{Could not determine version of Postgres from: $db->{slurp}}; + } + $db->{version} = $1; + $db->{ok} = 0; + delete $arg->{versiononly}; + ## Remove this from the returned hash + pop @{$info->{db}}; + redo; + } + ## If we were provided with a regex, check and bail if it fails elsif ($arg->{regex}) { if ($db->{slurp} !~ $arg->{regex}) { @@ -1147,22 +1193,6 @@ sub run_command { } - ## If we are running different queries based on the version, - ## find the version we are using, replace the string as needed, - ## then re-run the command to this connection. - if ($arg->{version}) { - if ($db->{error}) { - ndie $db->{error}; - } - if ($db->{slurp} !~ /PostgreSQL (\d+\.\d+)/) { - ndie qq{Could not determine version of Postgres!\n}; - } - $db->{version} = $1; - $string = $arg->{version}{$db->{version}} || $arg->{oldstring}; - delete $arg->{version}; - redo; - } - } ## end each database @@ -1193,7 +1223,9 @@ sub verify_version { ## Check if the backend can handle the current action my $limit = $testaction{lc $action} || ''; - return if ! $limit; + my $versiononly = shift || 0; + + return if ! $limit and ! $versiononly; ## We almost always need the version, so just grab it for any limitation $SQL = q{SELECT setting FROM pg_settings WHERE name = 'server_version'}; @@ -1211,6 +1243,10 @@ sub verify_version { } my ($sver,$smaj,$smin) = ($1,$2,$3); + if ($versiononly) { + return $sver; + } + if ($limit =~ /VERSION: ((\d+)\.(\d+))/) { my ($rver,$rmaj,$rmin) = ($1,$2,$3); if ($smaj < $rmaj or ($smaj==$rmaj and $smin < $rmin)) { @@ -3830,6 +3866,57 @@ sub check_checkpoint { } ## end of check_checkpoint +sub check_disabled_triggers { + + ## Checks how many disabled triggers are in the database + ## Supports: Nagios, MRTG + ## Warning and critical are integers, defaults to 1 + + my ($warning, $critical) = validate_range + ({ + type => 'positive integer', + default_warning => 1, + default_critical => 1, + forcemrtg => 1, + }); + + $SQL = q{SELECT tgrelid::regclass, tgname, tgenabled FROM pg_trigger WHERE tgenabled IS TRUE ORDER BY tgname}; + my $SQL83 = q{SELECT tgrelid::regclass, tgname, tgenabled FROM pg_trigger WHERE tgenabled = 'D' ORDER BY tgname}; + + my $info = run_command($SQL, { version => [ ">8.2 $SQL83" ] } ); + + my $count = 0; + my $dislis = ''; + for (@{$info->{db}}) { + $db = $_; + while ($db->{slurp} =~ / (.+?)\s+\| (.+?)\s+\| (\w+)/gsm) { + my ($table,$trigger,$setting) = ($1,$2,$3); + $count++; + $dislis .= " $table=>$trigger"; + } + if ($MRTG) { + do_mrtg({one => $count}); + return; + } + } + + my $msg = "Disabled triggers: $count$dislis"; + + if ($critical and $count >= $critical) { + add_critical $msg; + } + elsif ($warning and $count >= $warning) { + add_warning $msg; + } + else { + add_ok $msg; + } + + return; + +} ## end of check_disabled_triggers + + sub show_dbstats { ## Returns values from the pg_stat_database view @@ -3842,10 +3929,10 @@ sub show_dbstats { }); my $SQL = q{SELECT datname,numbackends,xact_commit,xact_rollback,blks_read,blks_hit}; - $psql_version >= 8.3 and $SQL .= q{,tup_returned,tup_fetched,tup_inserted,tup_updated,tup_deleted}; $SQL .= q{ FROM pg_catalog.pg_stat_database}; + (my $SQL2 = $SQL) =~ s/blks_hit/blks_hit,tup_returned,tup_fetched,tup_inserted,tup_updated,tup_deleted/; - my $info = run_command($SQL, {regex => qr{\w}} ); + my $info = run_command($SQL, {regex => qr{\w}, version => [ ">8.2 $SQL2" ] } ); for $db (@{$info->{db}}) { SLURP: for my $row (split /\n/ => $db->{slurp}) { @@ -3879,7 +3966,7 @@ sub show_dbstats { B - a Postgres monitoring script for Nagios, MRTG, Cacti, and others -This documents describes check_postgres.pl version 2.7.3 +This documents describes check_postgres.pl version 2.8.0 =head1 SYNOPSIS @@ -4010,7 +4097,7 @@ it defaults to 'postgres'. =item B<--dbpass=PASSWORD> -Provides the password to connect to the database with. Use of this option is highly discouraged. +Provides the password to connect to the database with. Use of this option is highly discouraged. Instead, one should use a .pgpass file. =item B<--dbservice=NAME> @@ -4447,6 +4534,21 @@ Example 1: Grab the stats for a database named "products" on host "willow": check_postgres_dbstats --dbhost willow --dbname products +=head2 B + +(C) Checks on the number of disabled triggers inside the database. +The I<--warning> and I<--critical> options are the number of such triggers found, and both +default to "1", as in normal usage having disabled triggers is a dangerous event. If the +database being checked is 8.3 or higher, the check is for the number of triggers that are +in a 'disabled' status (as opposed to being 'always' or 'replica'). The output will show +the name of the table and the name of the trigger for each disabled trigger. + +Example 1: Make sure that there are no disabled triggers + + check_postgres_disabled_triggers + +For MRTG output, returns the number of disabled triggers on the first line. + =head2 B (C) Checks on the available physical disk space used by Postgres. This action requires @@ -5133,6 +5235,10 @@ Items not specifically attributed are by Greg Sabino Mullane. =over 4 +=item B (February ??, 2009) + + Add the 'disabled_triggers' check. + =item B (February 10, 2009) Make the sequence action check if sequence being used for a int4 column and -- 2.39.5