├── README.md ├── check-es-indexes.sh ├── check_activemq ├── check_activemq_mem ├── check_haproxy ├── check_megaraid_sas ├── check_ssd_attribs.pl ├── check_ssl_certificate ├── check_ssllabs.sh ├── check_system_pp ├── mon_maria.pl ├── monitor.rc ├── monitor.sh ├── nagios-lvm-space.sh ├── nsca-receive-http.cgi ├── parse-backupninja-logs.sh ├── reset_ssllabs.sh ├── send_nsca_http.pl ├── split-hotfolder.sh └── ygrep /README.md: -------------------------------------------------------------------------------- 1 | sysadmin 2 | ======== 3 | 4 | System-admin scripts 5 | 6 | monitor.sh and monitor.rc 7 | ------------------------- 8 | 9 | nagios nrpe alternative, use with cron and send_nsca to have a minimalistic 10 | nrpe alternative. Can be used for 'unreachable' hosts. 11 | 12 | Host-specific configuration (paths / checks to run) goes in monitor.rc file 13 | 14 | If you are running a MQTT server, you can have monitor.sh also report status updates and warnings to a MQTT topic. This required mosquitto_pub to be present on the system. 15 | 16 | check_ssllabs.sh 17 | ---------------- 18 | 19 | Check Qualys ssllabs.com site for score/configuration of a https certificate 20 | Trigger nagios warning/error when score drops below 85. 21 | Don't run more then 1x per hour. Run the reset_ssllabs.sh script no more then 1x per day. 22 | It can take up to 5 minutes between a reset and a cache-update. 23 | 24 | To be used with Nagios/Icinga compatible monitoring systems 25 | 26 | check_ssd_attribs.pl 27 | -------------------- 28 | 29 | Nagios/Icinga check-script to monitor various SMART attributes on (SSD) drives. Will calculate 30 | the percentage of TBW (total bytes written), and monitor various other attributes used by 31 | (for example) Samsung 840 Pro ssd's. 32 | 33 | To be used with Nagios/Icinga compatible monitoring systems 34 | 35 | mon_maria.pl 36 | ------------ 37 | 38 | Monitoring script for galera clusters, check correct values in the following settings: 39 | - wsrep_local_state 40 | - wsrep_on 41 | - wsrep_cluster_size 42 | And the option to force a node offline manually. This script can be used as a loadbalancer check script to judge the health of the cluster-node. 43 | 44 | check_activemq 45 | -------------- 46 | 47 | Will monitor the amount of messages and consumers in various activeMQ queues, and alert if there 48 | are too many messages, or too little consumers. Limits can be supplied per queue, with a fallback 49 | default option. Limits can be specified using a cron-like syntax to specify when they should apply. 50 | 51 | The config, and URL to the activeMQ webpage should be specified in the code at this time. 52 | 53 | To be used with Nagios/Icinga compatible monitoring systems 54 | 55 | check_activemq_mem 56 | ------------------ 57 | 58 | Check the ActiveMQ memory (Store/Memory/Temp) usage by parsing the ActiveMQ webpage 59 | 60 | To be used with Nagios/Icinga compatible monitoring systems 61 | 62 | 63 | check-es-indexes 64 | ---------------- 65 | 66 | Check if the specified ElasticSearch index(es) have data in them. The URL to the ES instance, 67 | and the indexes to be monitored need to be specified in the script. 68 | 69 | To be used with Nagios/Icinga compatible monitoring systems 70 | 71 | 72 | check_haproxy 73 | ------------- 74 | 75 | By: Stéphane Urbanovski 76 | 77 | To be used with Nagios/Icinga compatible monitoring systems 78 | 79 | check_megaraid_sas 80 | ------------------ 81 | 82 | By: Jonathan Delgado, delgado@molbio.mgh.harvard.edu 83 | With various patches. 84 | 85 | Check the array and disk status of disks attached to megaraid controllers. Uses 'MegaCli'. 86 | This version is patched to handle JBOD disks and optionally ignore 'other' errors as reported by megacli, 87 | 88 | To be used with Nagios/Icinga compatible monitoring systems 89 | 90 | check_ssl_certificate 91 | --------------------- 92 | 93 | By: David Alden 94 | Patched to alert on expired certificates 95 | 96 | This script will check if an SSL certificate is going to expire. 97 | 98 | To be used with Nagios/Icinga compatible monitoring systems 99 | 100 | check_system_pp 101 | --------------- 102 | 103 | By: FBA? 104 | Patched to read processes and ports to monitor from seperate files 105 | 106 | Check if processes and ports are running/open as expected. 107 | 108 | To be used with Nagios/Icinga compatible monitoring systems 109 | 110 | nagios-lvm-space 111 | ---------------- 112 | 113 | Check free (unallocated) space in LVM volume groups 114 | 115 | To be used with Nagios/Icinga compatible monitoring systems 116 | 117 | parse-backupninja-logs.sh 118 | ------------------------- 119 | 120 | Check the status of backups made by backupninja by parsing it's logfiles. 121 | 122 | To be used with Nagios/Icinga compatible monitoring systems 123 | 124 | split-hotfolder.sh 125 | ------------------ 126 | 127 | Move files coming into a directory to one of multiple other directories. 128 | -------------------------------------------------------------------------------- /check-es-indexes.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | CURL=/usr/bin/curl 4 | 5 | HOSTNAME="$1" 6 | BASEURL="http://${HOSTNAME}:9200" 7 | 8 | URLS=( 9 | 'some/index' 10 | 'some/other/index' 11 | ) 12 | 13 | ERRSTR="" 14 | 15 | for URL in "${URLS[@]}" 16 | do 17 | DATA="`${CURL} -s ${BASEURL}/${URL}/_count | awk -F, '{print $1}' | tr '{}:' ' '`" 18 | 19 | COUNT="`echo ${DATA} | awk '{print $2}'`" 20 | if [ $COUNT -lt 1 ]; then 21 | ERRSTR="${ERRSTR}${URL} empty " 22 | fi 23 | done 24 | 25 | if [ ! -z "${ERRSTR}" ]; then 26 | echo "WARNING ElasticSearch indexes empty: ${ERRSTR}" 27 | exit 1 28 | else 29 | echo "OK - ElasticSearch indexes are populated" 30 | exit 0 31 | fi 32 | 33 | -------------------------------------------------------------------------------- /check_activemq: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # Check_ActiveMQ_Smart 4 | # © 2012 -- Sig-I/O Automatisering 5 | # Version: 2012/05/15 -- mark@sig-io.nl 6 | 7 | # For some reason, nagios doesn't like strict/warnings, though there weren't any on the commandline 8 | #use strict; 9 | #use warnings; 10 | use XML::Simple; 11 | use DateTime::Event::Cron; 12 | use RRD::Simple (); 13 | my $now = DateTime->now; 14 | 15 | # ---------------------------------------------------------- CONFIGURATION 16 | # Format of configuration: 17 | # "QueueName" => [ "cron-spec", limit, "cron-spec", limit, ... ], 18 | # cronspec in default 5 number cron format: "* * * * *" 19 | # minute 0-59 20 | # hour 0-23 21 | # day of month 1-31 22 | # month 1-12 (or names, see below) 23 | # day of week 0-7 (0 or 7 is Sun, or use names) 24 | # If multiple cron-spec's match, only the first one will be used 25 | # If no cron-spec's match, the queue is ignored 26 | # limit as integer: 27 | # -1 == ignore this queue completely 28 | # 0 or positive == max number of items in the queue 29 | # Queue-name "default" is the fallback rule 30 | 31 | my %config = ( 32 | "ActiveMQ.DLQ" => [ 33 | "* * * * *", "50" ], 34 | "some.queue" => [ 35 | "40-59 20 * * *", 5000, # Daily from 20:40 36 | "* 21 * * *", 5000, # to 37 | "0-15 22 * * *", 5000, # 22:15 38 | "0-50 0 * * *", 5000, # And after midnight 39 | "* * * * *", 3000 ], 40 | "some.otherQueue" => [ 41 | "40-59 20 * * *", 5000, 42 | "0-30 0 * * *", 5000, 43 | "* * * * *", 500 ], 44 | "queue.commandLine" => [ 45 | "* * * * *", 1000, ], 46 | "default" => [ "* * * * *", "200" ], 47 | ); 48 | 49 | my $verbose = 0; 50 | my $url = "http://192.168.102.200:8161/admin/xml/queues.jsp"; 51 | $now->set_time_zone( 'Europe/Amsterdam' ); 52 | 53 | # ---------------------------------------------------------- END CONFIG 54 | 55 | 56 | # ---------------------------------------------------------- SUBROUTINES 57 | sub getlimit($) 58 | { 59 | my $found = 0; 60 | my $queue = shift; 61 | my $limit = 0; 62 | 63 | if (exists $config{$queue}) 64 | { 65 | my @configdata = @{ $config{$queue} }; 66 | my $numrules = int( scalar(@configdata) / 2); 67 | my $i = 0; 68 | while ($i < $numrules ) 69 | { 70 | # print "Rule $i == '" . $configdata[$i*2] . "'\n"; 71 | my $cron = DateTime::Event::Cron->new( $configdata[$i*2]); 72 | if ( $cron->match( $now ) ) 73 | { 74 | $limit = $configdata[$i*2 +1]; 75 | $found++; 76 | # print "Found matching rule ($i): " . $configdata[$i*2] . " with limit $limit !\n"; 77 | $i = $numrules; 78 | } 79 | $i++; 80 | } 81 | 82 | if ( ( $queue eq "default" ) && ( $found == 0 ) ) 83 | { 84 | # No matching rule found, not even a default rule 85 | return -2; 86 | } 87 | } 88 | else # Try again with 'default' rules 89 | { 90 | if ( $queue ne "default" ) 91 | { 92 | # print "No specific rules found for $queue, trying again with default\n"; 93 | # Retry resolving with default rule: 94 | $limit = &getlimit("default"); 95 | } 96 | } 97 | 98 | # We have a rule for this queue, but it doesn't match the time, 99 | # Fallback to default 100 | if ( ( $found == 0 ) && ( $queue ne "default" ) ) 101 | { 102 | return &getlimit("default"); 103 | } 104 | 105 | return $limit; 106 | } 107 | 108 | # -------------------------------------------------------------------------- MAIN 109 | 110 | my $store; 111 | my $memory; 112 | my $temp; 113 | 114 | if ( defined $ARGV[0] ) 115 | { 116 | $url = $ARGV[0]; 117 | } 118 | 119 | 120 | my $dump = qx|/usr/bin/curl -s $url|; 121 | my $xmldata = XMLin($dump); 122 | 123 | my $queue; 124 | my $data; 125 | my $issuecount = 0; 126 | my $issues = ""; 127 | 128 | printf STDERR "%-50s %4s %7s %7s %4s limit: %4d\n", "Queue Name", "Cons", "De-Q", "En-Q", "Size", "Lim" if $verbose; 129 | while ( ($queue, $data) = each(%{$xmldata->{queue}}) ) 130 | { 131 | my ( $consumers, $enqueue, $dequeue, $size); 132 | my %stats = %{$data->{stats}}; 133 | 134 | $consumers = $stats{consumerCount}; 135 | $dequeue = $stats{dequeueCount}; 136 | $enqueue = $stats{enqueueCount}; 137 | $size = $stats{size}; 138 | 139 | my $rrd = RRD::Simple->new( file => "/var/rrd/$queue.rrd" ); 140 | if ( ! -e "/var/rrd/$queue.rrd" ) 141 | { 142 | #printf STDERR "No rrd-file present for queue: $queue\n"; 143 | $rrd->create( consumers => "GAUGE", 144 | dequeue => "COUNTER", 145 | enqueue => "COUNTER", 146 | size => "GAUGE" ); 147 | } 148 | 149 | $rrd->update( consumers => $consumers, dequeue => $dequeue, enqueue => $enqueue, size => $size ); 150 | 151 | my $limit = &getlimit($queue); 152 | printf STDERR "%-50s %4d %7d %7d %4d limit: %4s\n", $queue, $consumers, $dequeue, $enqueue, $size, $limit if $verbose; 153 | next if ( $limit == -1 ); # Skip this queue 154 | 155 | if ( $consumers == 0 ) 156 | { 157 | if ( $queue ne "ActiveMQ.DLQ" ) # This queue always has 0 consumers 158 | { 159 | $issuecount++; 160 | $issues .= "$queue has NO consumers "; 161 | } 162 | } 163 | if ( $size > $limit ) 164 | { 165 | $issuecount++; 166 | $issues .= "$queue is getting full ($size/$limit) "; 167 | } 168 | } 169 | 170 | my $retval = $issuecount; 171 | my $state = "OK"; 172 | $retval = 2, $state = "CRITICAL" if ( $retval >= 2 ); 173 | $state = "WARNING" if ( $retval == 1 ); 174 | $issues = "Everything reported OK" if $issues eq ""; 175 | 176 | $url =~ s/xml\///; 177 | printf "%s: ActiveMQ: %s url\n", $state, $issues, $url; 178 | exit ($retval); 179 | -------------------------------------------------------------------------------- /check_activemq_mem: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | 3 | # Check ActiveMQ store memory usage 4 | # Mark Janssen -- Sig-I/O Automatisering 5 | # 2013/04/06 6 | # License: GNU GPL v2 7 | 8 | use strict; 9 | use warnings; 10 | use XML::LibXML; 11 | 12 | my $store; 13 | my $memory; 14 | my $temp; 15 | my $issues = 0; 16 | 17 | my $url = $ARGV[0]; 18 | my $warn = $ARGV[1]; 19 | my $crit = $ARGV[2]; 20 | 21 | #print "URL / Levels: $url, $warn, $crit\n"; 22 | 23 | my $dump = qx|/usr/bin/curl -s $url|; 24 | 25 | #print "Got data: $dump\n"; 26 | 27 | my $parser = new XML::LibXML; 28 | my $doc = $parser->parse_string( $dump ); 29 | 30 | my $root = $doc->getDocumentElement ; 31 | 32 | my $nodes = $root->find('/html/body/table/tr/td') ; 33 | 34 | my $i = 6; 35 | 36 | while( $i < @$nodes ) 37 | { 38 | my $key = $nodes->[$i++]->toString; 39 | $key =~ s/<\/td>//; 40 | $key =~ s///; 41 | my $value = $nodes->[$i++]->toString; 42 | $value =~ s/<\/b><\/td>//; 43 | $value =~ s///; 44 | # print "Got key/value: '$key / $value'\n"; 45 | 46 | $issues++ if ( $value >= $crit ); 47 | $issues++ if ( $value >= $warn ); 48 | 49 | $store = $value if ( $key =~ /Store percent used/ ); 50 | $memory = $value if ( $key =~ /Memory percent used/ ); 51 | $temp = $value if ( $key =~ /Temp percent used/ ); 52 | } 53 | 54 | my $retval = $issues; 55 | my $state = "OK"; 56 | $retval = 2, $state = "CRITICAL" if ( $retval >= 2 ); 57 | $state = "WARNING" if ( $retval == 1 ); 58 | 59 | printf "%s: ActiveMQ memory usage: %d/%d/%d (store/memory/temp)\n", $state, $store, $memory, $temp; 60 | exit ($retval); 61 | -------------------------------------------------------------------------------- /check_haproxy: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | # 3 | # Copyright (c) 2010 Stéphane Urbanovski 4 | # 5 | # This program is free software; you can redistribute it and/or 6 | # modify it under the terms of the GNU General Public License 7 | # as published by the Free Software Foundation; either version 2 8 | # of the License, or (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty 12 | # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # you should have received a copy of the GNU General Public License 16 | # along with this program (or with Nagios); if not, write to the 17 | # Free Software Foundation, Inc., 59 Temple Place - Suite 330, 18 | # Boston, MA 02111-1307, USA 19 | # 20 | # $Id: $ 21 | 22 | use strict; # should never be differently :-) 23 | use warnings; 24 | 25 | 26 | use Locale::gettext; 27 | use File::Basename; # get basename() 28 | 29 | use POSIX qw(setlocale); 30 | use Time::HiRes qw(time); # get microtime 31 | use POSIX qw(mktime); 32 | 33 | use Nagios::Plugin ; 34 | 35 | use LWP::UserAgent; # http client 36 | use HTTP::Request; # used by LWP::UserAgent 37 | use HTTP::Status; # to get http err msg 38 | use IO::Socket; # To use unix Sockets 39 | 40 | 41 | use Data::Dumper; 42 | 43 | 44 | my $PROGNAME = basename($0); 45 | '$Revision: 1.0 $' =~ /^.*(\d+\.\d+) \$$/; # Use The Revision from RCS/CVS/SVN 46 | my $VERSION = $1; 47 | 48 | my $DEBUG = 0; 49 | my $TIMEOUT = 9; 50 | 51 | # i18n : 52 | setlocale(LC_MESSAGES, ''); 53 | textdomain('nagios-plugins-perl'); 54 | 55 | 56 | my $np = Nagios::Plugin->new( 57 | version => $VERSION, 58 | blurb => _gt('Plugin to check HAProxy stats url'), 59 | usage => "Usage: %s [ -v|--verbose ] -u [-t ] [-U ] [-P ] [ -c|--critical= ] [ -w|--warning= ] [ -b|--critical-backends=", 60 | timeout => $TIMEOUT+1 61 | ); 62 | $np->add_arg ( 63 | spec => 'debug|d', 64 | help => _gt('Debug level'), 65 | default => 0, 66 | ); 67 | $np->add_arg ( 68 | spec => 'username|U=s', 69 | help => _gt('Username for HTTP Auth'), 70 | required => 0, 71 | ); 72 | $np->add_arg ( 73 | spec => 'password|P=s', 74 | help => _gt('Password for HTTP Auth'), 75 | required => 0, 76 | ); 77 | $np->add_arg ( 78 | spec => 'w=f', 79 | help => _gt('Warning request time threshold (in seconds)'), 80 | default => 2, 81 | label => 'FLOAT' 82 | ); 83 | $np->add_arg ( 84 | spec => 'c=f', 85 | help => _gt('Critical request time threshold (in seconds)'), 86 | default => 10, 87 | label => 'FLOAT' 88 | ); 89 | $np->add_arg ( 90 | spec => 'url|u=s', 91 | help => _gt('URL of the HAProxy csv statistics page HTTP or unix Socket.'), 92 | required => 1, 93 | ); 94 | $np->add_arg ( 95 | spec => 'critical-backends|b=s', 96 | help => _gt('List of critical backend, if set other backend are only warning backend'), 97 | required => 0, 98 | ); 99 | 100 | 101 | $np->getopts; 102 | 103 | $DEBUG = $np->opts->get('debug'); 104 | my $verbose = $np->opts->get('verbose'); 105 | my $username = $np->opts->get('username'); 106 | my $password = $np->opts->get('password'); 107 | my $crit_backends = $np->opts->get('critical-backends'); 108 | my @crit_backends_list; 109 | if ( defined ( $crit_backends ) ) { 110 | @crit_backends_list = split(',',$crit_backends); 111 | } 112 | 113 | # Thresholds : 114 | # time 115 | my $warn_t = $np->opts->get('w'); 116 | my $crit_t = $np->opts->get('c'); 117 | 118 | my $url = $np->opts->get('url'); 119 | 120 | 121 | # Create a LWP user agent object: 122 | my $ua = new LWP::UserAgent( 123 | 'env_proxy' => 0, 124 | 'timeout' => $TIMEOUT, 125 | ); 126 | $ua->agent(basename($0)); 127 | 128 | # Workaround for LWP bug : 129 | $ua->parse_head(0); 130 | 131 | # For csv data 132 | my $stats=""; 133 | 134 | my $timer = time(); 135 | if ( $url =~ /^http/ ) { 136 | if ( defined($ENV{'http_proxy'}) ) { 137 | # Normal http proxy : 138 | $ua->proxy(['http'], $ENV{'http_proxy'}); 139 | # Https must use Crypt::SSLeay https proxy (to use CONNECT method instead of GET) 140 | $ENV{'HTTPS_PROXY'} = $ENV{'http_proxy'}; 141 | } 142 | # Build and submit an http request : 143 | my $request = HTTP::Request->new('GET', $url); 144 | # Authenticate if username and password are supplied 145 | if ( defined($username) && defined($password) ) { 146 | $request->authorization_basic($username, $password); 147 | } 148 | my $http_response = $ua->request( $request ); 149 | 150 | if ( $http_response->is_error() ) { 151 | my $err = $http_response->code." ".status_message($http_response->code)." (".$http_response->message.")"; 152 | $np->add_message(CRITICAL, _gt("HTTP error: ").$err ); 153 | } elsif ( ! $http_response->is_success() ) { 154 | my $err = $http_response->code." ".status_message($http_response->code)." (".$http_response->message.")"; 155 | $np->add_message(CRITICAL, _gt("Internal error: ").$err ); 156 | } 157 | if ( $http_response->is_success() ) { 158 | $stats = $http_response->content; 159 | } 160 | 161 | }elsif ( $url =~ /^\// ) { 162 | my $sock = new IO::Socket::UNIX ( 163 | Peer => "$url", 164 | Type => SOCK_STREAM, 165 | Timeout => 1); 166 | if ( !$sock ) { 167 | my $err = "Can't connect to unix socket"; 168 | $np->add_message(CRITICAL, _gt("Internal error: ").$err ); 169 | }else{ 170 | print $sock "show stat\n"; 171 | while(my $line = <$sock>){ 172 | $stats.=$line; 173 | } 174 | } 175 | }else { 176 | my $err = "Can't detect socket type"; 177 | $np->add_message(CRITICAL, _gt("Internal error: ").$err ); 178 | } 179 | $timer = time()-$timer; 180 | 181 | 182 | 183 | my $status = $np->check_threshold( 184 | 'check' => $timer, 185 | 'warning' => $warn_t, 186 | 'critical' => $crit_t, 187 | ); 188 | 189 | $np->add_perfdata( 190 | 'label' => 't', 191 | 'value' => sprintf('%.6f',$timer), 192 | 'min' => 0, 193 | 'uom' => 's', 194 | 'threshold' => $np->threshold() 195 | ); 196 | 197 | if ( $status > OK ) { 198 | $np->add_message($status, sprintf(_gt("Response time degraded: %.6fs !"),$timer) ); 199 | } 200 | 201 | 202 | my $message = 'msg'; 203 | 204 | 205 | 206 | 207 | ($status, $message) = $np->check_messages(); 208 | 209 | if ( $status == OK && $stats ne "") { 210 | 211 | if ($DEBUG) { 212 | print "------------------===csv output===------------------\n$stats\n-----------------------------------------------------\n"; 213 | print "t=".$timer."s\n"; 214 | }; 215 | 216 | my @fields = (); 217 | my @rows = split(/\n/,$stats); 218 | if ( $rows[0] =~ /#\ \w+/ ) { 219 | $rows[0] =~ s/#\ //; 220 | @fields = split(/\,/,$rows[0]); 221 | } else { 222 | $np->nagios_exit(UNKNOWN, _gt("Can't find csv header !") ); 223 | } 224 | 225 | my %stats = (); 226 | for ( my $y = 1; $y < $#rows; $y++ ) { 227 | my @values = split(/\,/,$rows[$y]); 228 | if ( !defined($stats{$values[0]}) ) { 229 | $stats{$values[0]} = {}; 230 | } 231 | if ( !defined($stats{$values[0]}{$values[1]}) ) { 232 | $stats{$values[0]}{$values[1]} = {}; 233 | } 234 | for ( my $x = 2,; $x <= $#values; $x++ ) { 235 | # $stats{pxname}{svname}{valuename} 236 | $stats{$values[0]}{$values[1]}{$fields[$x]} = $values[$x]; 237 | } 238 | } 239 | # print Dumper(\%stats); 240 | my %stats2 = (); 241 | my $okMsg = ''; 242 | foreach my $pxname ( keys(%stats) ) { 243 | $stats2{$pxname} = { 244 | 'act' => 0, 245 | 'acttot' => 0, 246 | 'bck' => 0, 247 | 'bcktot' => 0, 248 | 'scur' => 0, 249 | 'slim' => 0, 250 | }; 251 | foreach my $svname ( keys(%{$stats{$pxname}}) ) { 252 | if ( $stats{$pxname}{$svname}{'type'} eq '2' ) { 253 | my $svstatus = $stats{$pxname}{$svname}{'status'} eq 'UP'; 254 | my $active = $stats{$pxname}{$svname}{'act'} eq '1'; 255 | my $activeDescr = $active ? _gt("Active service") :_gt("Backup service") ; 256 | if ( $stats{$pxname}{$svname}{'status'} eq 'UP' ) { 257 | logD( sprintf(_gt("%s '%s' is up on '%s' proxy."),$activeDescr,$svname,$pxname) ); 258 | } elsif ( $stats{$pxname}{$svname}{'status'} eq 'DOWN' ) { 259 | if ( defined($crit_backends) ) { 260 | if ( grep(/^$pxname$/,@crit_backends_list) ) { 261 | $np->add_message(CRITICAL, sprintf(_gt("%s '%s' is DOWN on '%s' proxy !"),$activeDescr,$svname,$pxname) ); 262 | }else{ 263 | $np->add_message(WARNING, sprintf(_gt("%s '%s' is DOWN on '%s' proxy !"),$activeDescr,$svname,$pxname) ); 264 | } 265 | }else{ 266 | $np->add_message(CRITICAL, sprintf(_gt("%s '%s' is DOWN on '%s' proxy !"),$activeDescr,$svname,$pxname) ); 267 | } 268 | } 269 | if ( $stats{$pxname}{$svname}{'act'} eq '1' ) { 270 | $stats2{$pxname}{'acttot'}++; 271 | $stats2{$pxname}{'act'} += $svstatus; 272 | 273 | } elsif ($stats{$pxname}{$svname}{'bck'} eq '1') { 274 | $stats2{$pxname}{'bcktot'}++; 275 | $stats2{$pxname}{'bck'} += $svstatus; 276 | } 277 | $stats2{$pxname}{'scur'} += $stats{$pxname}{$svname}{'scur'}; 278 | logD( "Current sessions : ".$stats{$pxname}{$svname}{'scur'} ); 279 | 280 | } elsif ( $stats{$pxname}{$svname}{'type'} eq '0' ) { 281 | $stats2{$pxname}{'slim'} = $stats{$pxname}{$svname}{'slim'}; 282 | } 283 | } 284 | if ( $stats2{$pxname}{'acttot'} > 0 ) { 285 | $okMsg .= ' '.$pxname.' (Active: '.$stats2{$pxname}{'act'}.'/'.$stats2{$pxname}{'acttot'}; 286 | if ( $stats2{$pxname}{'bcktot'} > 0 ) { 287 | $okMsg .= ' , Backup: '.$stats2{$pxname}{'bck'}.'/'.$stats2{$pxname}{'bcktot'}; 288 | } 289 | $okMsg .= ')'; 290 | $np->add_perfdata( 291 | 'label' => 'sess_'.$pxname, 292 | 'value' => $stats2{$pxname}{'scur'}, 293 | 'min' => 0, 294 | 'uom' => 'sessions', 295 | 'max' => $stats2{$pxname}{'slim'}, 296 | ); 297 | } 298 | } 299 | 300 | # print Dumper(\%stats2); 301 | ($status, $message) = $np->check_messages('join' => ' '); 302 | 303 | if ( $status == OK ) { 304 | $message = $okMsg; 305 | 306 | } 307 | 308 | } 309 | # if ( $verbose ) { 310 | # ($status, $message) = $np->check_messages('join' => '
','join_all' => '
'); 311 | # } else { 312 | # ($status, $message) = $np->check_messages('join' => '
'); 313 | # } 314 | 315 | 316 | $np->nagios_exit($status, $message ); 317 | 318 | 319 | sub logD { 320 | print STDERR 'DEBUG: '.$_[0]."\n" if ($DEBUG); 321 | } 322 | sub logW { 323 | print STDERR 'WARNING: '.$_[0]."\n" if ($DEBUG); 324 | } 325 | # Gettext wrapper 326 | sub _gt { 327 | return gettext($_[0]); 328 | } 329 | 330 | 331 | __END__ 332 | 333 | =head1 NAME 334 | 335 | This Nagios plugins check the statistics url provided by HAProxy (http://haproxy.1wt.eu/). 336 | 337 | 338 | =head1 NAGIOS CONGIGURATIONS 339 | 340 | In F you have to add : 341 | 342 | define command { 343 | command_name check_haproxy 344 | command_line $USER1$/check_haproxy.pl -u $ARG1$ 345 | } 346 | 347 | 348 | In F you just have to add something like : 349 | 350 | define service { 351 | host_name haproxy.exemple.org 352 | normal_check_interval 10 353 | retry_check_interval 5 354 | contact_groups linux-admins 355 | service_description HAProxy 356 | check_command check_haproxy!http://haproxy.exemple.org/haproxy?stats;csv 357 | } 358 | 359 | Or: 360 | 361 | define service { 362 | host_name haproxy.exemple.org 363 | normal_check_interval 10 364 | retry_check_interval 5 365 | contact_groups linux-admins 366 | service_description HAProxy 367 | check_command check_haproxy!/var/run/my_haproxy.sock 368 | } 369 | 370 | =head1 AUTHOR 371 | 372 | Stéphane Urbanovski 373 | 374 | David BERARD 375 | 376 | =cut 377 | -------------------------------------------------------------------------------- /check_megaraid_sas: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | 3 | # check_megaraid_sas Nagios plugin 4 | # Copyright (C) 2007 Jonathan Delgado, delgado@molbio.mgh.harvard.edu 5 | # 6 | # This program is free software; you can redistribute it and/or 7 | # modify it under the terms of the GNU General Public License 8 | # as published by the Free Software Foundation; either version 2 9 | # of the License, or (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program; if not, write to the Free Software 18 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | # 20 | # 21 | # Nagios plugin to monitor the status of volumes attached to a LSI Megaraid SAS 22 | # controller, such as the Dell PERC5/i and PERC5/e. If you have any hotspares 23 | # attached to the controller, you can specify the number you should expect to 24 | # find with the '-s' flag. 25 | # 26 | # The paths for the Nagios plugins lib and MegaCli may need to me changed. 27 | # 28 | # Code for correct RAID level reporting contributed by Frode Nordahl, 2009/01/12. 29 | # 30 | # $Author: delgado $ 31 | # $Revision: #12 $ $Date: 2010/10/18 $ 32 | # 2017/10/03: Mark Janssen -- Sig-I/O Automatisering: Added -v option for verbose logging 33 | # 2018/04/18: Mark Janssen -- Sig-I/O Automatisering: Handle JBOD disks 34 | # 2018/04/18: Mark Janssen -- Sig-I/O Automatisering: Add -O option to ignore 'other' errors 35 | # 36 | # KNOWN BUGS: 37 | # - Non-consecutive logical-disk numbers cause problems (LD0, LD3) 38 | 39 | use strict; 40 | use Getopt::Std; 41 | use lib qw(/usr/lib/nagios/plugins /usr/lib64/nagios/plugins); # possible pathes to your Nagios plugins and utils.pm 42 | use utils qw(%ERRORS); 43 | 44 | our($opt_h, $opt_v, $opt_s, $opt_o, $opt_O, $opt_m, $opt_p); 45 | 46 | 47 | getopts('hOvs:o:p:m:'); 48 | 49 | if ( $opt_h ) { 50 | print "Usage: $0 [-s number] [-m number] [-o number]\n"; 51 | print " -s is how many hotspares are attached to the controller\n"; 52 | print " -m is the number of media errors to ignore\n"; 53 | print " -p is the predictive error count to ignore\n"; 54 | print " -o is the number of other disk errors to ignore\n"; 55 | print " -O completely ignore 'other' errors\n"; 56 | print " -v verbose error reporting\n"; 57 | exit; 58 | } 59 | 60 | my $megacli = '/usr/local/sbin/megacli'; # the full path to your MegaCli binary 61 | my $megapostopt = '-NoLog'; # additional options to call at the end of MegaCli arguments 62 | 63 | my ($adapters); 64 | my $hotspares = 0; 65 | my $hotsparecount = 0; 66 | my $pdbad = 0; 67 | my $pdcount = 0; 68 | my $mediaerrors = 0; 69 | my $mediaallow = 0; 70 | my $prederrors = 0; 71 | my $predallow = 0; 72 | my $othererrors = 0; 73 | my $otherallow = 0; 74 | my $result = ''; 75 | my $status = 'OK'; 76 | 77 | sub max_state ($$) { 78 | my ($current, $compare) = @_; 79 | 80 | if (($compare eq 'CRITICAL') || ($current eq 'CRITICAL')) { 81 | return 'CRITICAL'; 82 | } elsif ($compare eq 'OK') { 83 | return $current; 84 | } elsif ($compare eq 'WARNING') { 85 | return 'WARNING'; 86 | } elsif (($compare eq 'UNKNOWN') && ($current eq 'OK')) { 87 | return 'UNKNOWN'; 88 | } else { 89 | return $current; 90 | } 91 | } 92 | 93 | sub exitreport ($$) { 94 | my ($status, $message) = @_; 95 | 96 | print STDOUT "$status: $message\n"; 97 | exit $ERRORS{$status}; 98 | } 99 | 100 | 101 | if ( $opt_s ) { 102 | $hotspares = $opt_s; 103 | } 104 | if ( $opt_m ) { 105 | $mediaallow = $opt_m; 106 | } 107 | if ( $opt_p ) { 108 | $predallow = $opt_p; 109 | } 110 | if ( $opt_o ) { 111 | $otherallow = $opt_o; 112 | } 113 | 114 | # Get the number of RAID controllers we have 115 | open (ADPCOUNT, "$megacli -adpCount $megapostopt |") 116 | || exitreport('UNKNOWN',"error: Could not execute $megacli -adpCount $megapostopt"); 117 | 118 | while () { 119 | if ( m/Controller Count:\s*(\d+)/ ) { 120 | $adapters = $1; 121 | last; 122 | } 123 | } 124 | close ADPCOUNT; 125 | 126 | ADAPTER: for ( my $adp = 0; $adp < $adapters; $adp++ ) { 127 | # Get the number of logical drives on this adapter 128 | open (LDGETNUM, "$megacli -LdGetNum -a$adp $megapostopt |") 129 | || exitreport('UNKNOWN', "error: Could not execute $megacli -LdGetNum -a$adp $megapostopt"); 130 | 131 | my ($ldnum); 132 | while () { 133 | if ( m/Number of Virtual drives configured on adapter \d:\s*(\d+)/i ) { 134 | $ldnum = $1; 135 | last; 136 | } 137 | } 138 | close LDGETNUM; 139 | 140 | LDISK: for ( my $ld = 0; $ld < $ldnum; $ld++ ) { 141 | # Get info on this particular logical drive 142 | open (LDINFO, "$megacli -LdInfo -L$ld -a$adp $megapostopt |") 143 | || exitreport('UNKNOWN', "error: Could not execute $megacli -LdInfo -L$ld -a$adp $megapostopt "); 144 | 145 | my ($size, $unit, $raidlevel, $ldpdcount, $state, $spandepth); 146 | while () { 147 | if ( m/Size\s*:\s*((\d+\.?\d*)\s*(MB|GB|TB))/ ) { 148 | $size = $2; 149 | $unit = $3; 150 | # Adjust MB to GB if that's what we got 151 | if ( $unit eq 'MB' ) { 152 | $size = sprintf( "%.0f", ($size / 1024) ); 153 | $unit= 'GB'; 154 | } 155 | } elsif ( m/State\s*:\s*(\w+)/ ) { 156 | $state = $1; 157 | if ( $state ne 'Optimal' ) { 158 | $status = 'CRITICAL'; 159 | } 160 | } elsif ( m/Number Of Drives\s*(per span\s*)?:\s*(\d+)/ ) { 161 | $ldpdcount = $2; 162 | } elsif ( m/Span Depth\s*:\s*(\d+)/ ) { 163 | $spandepth = $1; 164 | } elsif ( m/RAID Level\s*: Primary-(\d)/ ) { 165 | $raidlevel = $1; 166 | } 167 | } 168 | close LDINFO; 169 | 170 | # Report correct RAID-level and number of drives in case of Span configurations 171 | if ($ldpdcount && $spandepth > 1) { 172 | $ldpdcount = $ldpdcount * $spandepth; 173 | if ($raidlevel < 10) { 174 | $raidlevel = $raidlevel . "0"; 175 | } 176 | } 177 | 178 | $result .= "$adp:$ld:RAID-$raidlevel:$ldpdcount drives:$size$unit:$state "; 179 | 180 | } #LDISK 181 | close LDINFO; 182 | 183 | # Get info on physical disks for this adapter 184 | open (PDLIST, "$megacli -PdList -a$adp $megapostopt |") 185 | || exitreport('UNKNOWN', "error: Could not execute $megacli -PdList -a$adp $megapostopt "); 186 | 187 | my ($slotnumber,$fwstate); 188 | PDISKS: while () { 189 | if ( m/Slot Number\s*:\s*(\d+)/ ) { 190 | $slotnumber = $1; 191 | $pdcount++; 192 | } elsif ( m/(\w+) Error Count\s*:\s*(\d+)/ ) { 193 | if ( $1 eq 'Media') { 194 | $mediaerrors += $2; 195 | } else { 196 | $othererrors += $2; 197 | } 198 | } elsif ( m/Predictive Failure Count\s*:\s*(\d+)/ ) { 199 | $prederrors += $1; 200 | } elsif ( m/Firmware state\s*:\s*(\w+)/ ) { 201 | $fwstate = $1; 202 | if ( $fwstate eq 'Hotspare' ) { 203 | $hotsparecount++; 204 | } elsif ( $fwstate eq 'Online' ) { 205 | # Do nothing 206 | } elsif ( $fwstate eq 'JBOD' ) { 207 | # A pass-through drive 208 | } elsif ( $fwstate eq 'Unconfigured' ) { 209 | # A drive not in anything, or a non drive device 210 | $pdcount--; 211 | } elsif ( $slotnumber != 255 ) { 212 | $pdbad++; 213 | $status = 'CRITICAL'; 214 | } 215 | } 216 | } #PDISKS 217 | close PDLIST; 218 | } 219 | 220 | $result .= "Drives:$pdcount "; 221 | 222 | # Any bad disks? 223 | if ( $pdbad ) { 224 | $result .= "$pdbad Bad Drives "; 225 | } 226 | 227 | my $errorcount = $mediaerrors + $prederrors + $othererrors; 228 | # Were there any errors? 229 | if ( $errorcount ) { 230 | $result .= "($errorcount Errors) "; 231 | if ( ( $mediaerrors > $mediaallow ) || 232 | ( $prederrors > $predallow ) || 233 | ( ! $opt_O && ( $othererrors > $otherallow ) ) ) { 234 | $status = max_state($status, 'WARNING'); 235 | } 236 | } 237 | 238 | # Do we have as many hotspares as expected (if any) 239 | if ( $hotspares ) { 240 | if ( $hotsparecount < $hotspares ) { 241 | $status = max_state($status, 'WARNING'); 242 | $result .= "Hotspare(s):$hotsparecount (of $hotspares)"; 243 | } else { 244 | $result .= "Hotspare(s):$hotsparecount"; 245 | } 246 | } 247 | 248 | if ( $opt_v ) 249 | { 250 | $result .= " (errorcounts: M: $mediaerrors, O: $othererrors, P: $prederrors )" 251 | } 252 | 253 | exitreport($status, $result); 254 | -------------------------------------------------------------------------------- /check_ssd_attribs.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | 3 | # check_ssd_attribs 4 | # Copyright (C) 2016 Mark Janssen -- Sig-I/O Automatisering, mark@sig-io.nl 5 | # 6 | # This program is free software; you can redistribute it and/or 7 | # modify it under the terms of the GNU General Public License 8 | # as published by the Free Software Foundation; either version 2 9 | # of the License, or (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program; if not, write to the Free Software 18 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | # 20 | 21 | use strict; 22 | 23 | use Getopt::Std; 24 | use lib qw(/usr/lib/nagios/plugins /usr/lib64/nagios/plugins); # possible pathes to your Nagios plugins and utils.pm 25 | use utils qw(%ERRORS); 26 | 27 | our($opt_h, $opt_d, $opt_t, $opt_T, $opt_D); 28 | 29 | our $failcount = 0; 30 | our $warntext = ""; 31 | our $status = "OK"; 32 | 33 | getopts('hd:t:T:D'); 34 | 35 | if ( $opt_h ) { 36 | print "Usage: $0 -d drives [-t smartctl-device] [-T TBWritten]\n"; 37 | print " -d is the device to check (ex: /dev/sdb)\n"; 38 | print " -t is the device type for smartctl (ex: sat+megaraid,3)\n"; 39 | print " -T Warranted number of TB's written\n"; 40 | exit; 41 | } 42 | 43 | our $warrantytbs = 100; 44 | $warrantytbs = $opt_T if $opt_T; 45 | 46 | my $smartctl = '/usr/sbin/smartctl'; # Path to smartctl 47 | my $deviceopts = ""; 48 | $deviceopts .= "-d $opt_t " if $opt_t; 49 | $deviceopts .= "$opt_d" if $opt_d; 50 | 51 | open (SMARTDATA, "$smartctl $deviceopts -A -f brief |") || exitreport('UNKNOWN', "error: Could not execute $smartctl $deviceopts"); 52 | while( ) 53 | { 54 | next if $_ =~ /^smartctl/; 55 | next if $_ =~ /^Copyright/; 56 | next if $_ =~ /^$/; 57 | next if $_ =~ /^=== START/; 58 | next if $_ =~ /^SMART Attri/; 59 | next if $_ =~ /^Vendor Spec/; 60 | next if $_ =~ /^ID#/; 61 | next if $_ =~ /^ /; 62 | 63 | chomp; 64 | print "Got line: '$_'\n" if $opt_D; 65 | my ($id, $attr, $flags, $value, $worst, $thresh, $fail, $raw) = split; 66 | print "ID = $id, Attr = $attr, Fail = $fail, Raw = $raw\n" if $opt_D; 67 | 68 | if( $fail ne "-" ) 69 | { 70 | $failcount++; 71 | $warntext .= "Attr $attr fail: $fail "; 72 | } 73 | 74 | # 177: Wear leveling count 75 | # The value attribute is a percentage, starting at 100 76 | # A disk will continue running when it reaches <20% but then 77 | # Used-Block-Reserve will be going up. 78 | # Link: http://techreport.com/review/27436/the-ssd-endurance-experiment-two-freaking-petabytes/2 79 | if( $id == '177' ) # Wear Leveling count 80 | { 81 | $failcount++ if ( $value <= 60 ); 82 | $failcount++ if ( $value <= 20 ); 83 | $warntext .= "WLC: $value " if ( $value <= 70 ); 84 | } 85 | 86 | # 179: Used_Rsvd_Blk_Cnt_Tot 87 | # Total reserved block percentage still available 88 | if ( $id == '179' ) # Used_Rsvd_Blk_Cnt_Tot 89 | { 90 | $failcount++ if ( $value <= 80 ); 91 | $failcount++ if ( $value <= 40 ); 92 | $warntext .= "Reserved Blocks: $value% " if ($value <= 80); 93 | } 94 | 95 | # 181: Program_Fail_Cnt_Total 96 | # 182: Erase_Fail_Count_Total 97 | # 183: Runtime_Bad_Block 98 | # 187: Reported_Uncorrect 99 | if ( $id =~ /181|182|183|187/) 100 | { 101 | $failcount++ if ( $value <= 50 ); 102 | $warntext .= "$attr $value " if ($value <= 50); 103 | } 104 | 105 | # 241: TOTAL LBA's Written 106 | # Total number of LBA's (512 byte sectors) written to disk 107 | # SSD's are warranted against a MAX number of writes 108 | # SAMSUNG 840 PRO's are warranted against 72 TB or 40GB/day for 5 years 109 | if( $id == '241' ) # Total LBA's written / Samsung 110 | { 111 | my $tbs = int($raw * 512 / 1024 / 1024 / 1024 / 1024); 112 | my $warrantypercentage = int( $tbs / $warrantytbs * 100 ); 113 | $warntext .= "Total TB's written: $tbs out of warranted $warrantytbs ($warrantypercentage%)\n"; 114 | $failcount++ if ( $warrantypercentage >= 90 ); 115 | $failcount++ if ( $warrantypercentage >= 130 ); 116 | } 117 | } 118 | 119 | my $retval = $failcount; 120 | $retval = 2 if ($failcount >= 2 ); 121 | $status = "CRITICAL" if ($retval == 2); 122 | $status = "WARNING" if ($retval == 1); 123 | 124 | print STDOUT "$status: $warntext"; 125 | exit $retval; 126 | -------------------------------------------------------------------------------- /check_ssl_certificate: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | # 3 | # check_ssl_certificate 4 | # Nagios script to check ssl certificate expirations 5 | # 6 | # Copyright (c) 2006-2008 David Alden 7 | # 8 | # This program is free software; you can redistribute it and/or 9 | # modify it under the terms of the GNU General Public License 10 | # as published by the Free Software Foundation; either version 2 11 | # of the License, or (at your option) any later version. 12 | # 13 | # This program is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU General Public License 19 | # along with this program; if not, write to the Free Software 20 | # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 | # 22 | # 23 | # Changes: 24 | # 26/09/2014 sigio 25 | # - Report CRITICAL on expired certificates (was OK) 26 | # 27 | # 10/30/2008 dja 28 | # - fixed a bug which caused it to not deal with certs that expire 29 | # on a single digit day (thanks to Christian Sava, Kyle Smith & 30 | # Raphael Berlamont) 31 | # 32 | # 10/09/2007 dja 33 | # - fixed a bug which caused it to improperly report expired certs 34 | # (thanks to Hassan Alusesi for pointing this out) 35 | # - no longer use temporary files or Date::Manip 36 | # (thanks to tommybobbins on NagiosExchange) 37 | # - added the printing of the Common Name (CN) if verbose is specified 38 | # (thanks to mp72 on NagiosExchange) 39 | # 40 | # 41 | # Description: 42 | # This script will check if an SSL certificate is going to expire. For 43 | # example, to check the IMAP certificate on an imaps port: 44 | # 45 | # check_ssl_certificate -H 1.1.1.1 -p 993 46 | # 47 | # 48 | # Installation: 49 | # Edit this script, replacing the line: 50 | # use lib "/usr/lib/nagios/plugins"; 51 | # with the path to your nagios plugins directory (where utils.pm is 52 | # located). Also edit the line: 53 | # my $openssl = "/usr/bin/openssl"; 54 | # with the path to your openssl binary. Then copy the script into 55 | # your nagios plugins directory. 56 | # 57 | # 58 | use strict; 59 | use Time::Local; 60 | use Getopt::Long; 61 | use lib "/usr/lib64/nagios/plugins"; 62 | #use lib "/usr/lib/nagios/plugins/scripts/"; 63 | use utils qw(%ERRORS &print_revision &support &usage); 64 | 65 | my $PROGNAME="check_ssl_certificates"; 66 | my $REVISION="1.2"; 67 | 68 | # 69 | $ENV{PATH}="/usr/sbin:/usr/bin:/bin"; 70 | 71 | # 72 | my $openssl = "/usr/bin/openssl"; 73 | 74 | my $critical = 3; 75 | my $help; 76 | my $host; 77 | my $port = 443; 78 | my $additional = ''; 79 | my $verbose; 80 | my $version; 81 | my $warning = 15; 82 | 83 | # 84 | my %months = ('Jan' => 0, 'Feb' => 1, 'Mar' => 2, 'Apr' => 3, 'May' => 4, 85 | 'Jun' => 5, 'Jul' => 6, 'Aug' => 7, 'Sep' => 8, 'Oct' => 9, 86 | 'Nov' => 10, 'Dec' => 11); 87 | 88 | # 89 | Getopt::Long::Configure('bundling'); 90 | if (GetOptions( 91 | "a=s" => \$additional, 92 | "c:s" => \$critical, 93 | "h" => \$help, 94 | "H:s" => \$host, 95 | "o=s" => \$openssl, 96 | "p=i" => \$port, 97 | "v" => \$verbose, 98 | "V" => \$version, 99 | "w:s" => \$warning, 100 | ) == 0) { 101 | 102 | print_usage(); 103 | exit $ERRORS{'UNKNOWN'} 104 | } 105 | 106 | if ($version) { 107 | print_revision($PROGNAME, "\$Revision: $REVISION \$"); 108 | exit $ERRORS{'OK'}; 109 | } 110 | 111 | if ($help) { 112 | print_help(); 113 | exit $ERRORS{'OK'}; 114 | } 115 | 116 | if (! utils::is_hostname($host)) { 117 | usage(""); 118 | exit $ERRORS{'UNKNOWN'}; 119 | } 120 | 121 | open(OPENSSL, "$openssl s_client -connect $host:$port $additional < /dev/null 2>&1 | $openssl x509 -enddate -noout |") || 122 | die "unable to open $openssl: $!"; 123 | 124 | my $date; 125 | while () { 126 | if ($_ =~ /^notAfter=(.*)/) { 127 | $date = $1; 128 | chomp($date); 129 | # last; 130 | } 131 | } 132 | close(OPENSSL); 133 | 134 | $date =~ s/ +/ /g; 135 | 136 | my ($month, $day, $hour, $min, $sec, $year, $tz) = split(/[\s+|:]/, $date); 137 | #print "m=$month, d=$day, h=$hour, m=$min, s=$sec, y=$year, z=$tz\n"; 138 | 139 | my $daysLeft = int((timegm($sec, $min, $hour, $day, $months{$month}, $year - 1900) - time()) / 86400); 140 | 141 | my $cn="this certificate"; 142 | if ($verbose) { 143 | 144 | open(OPENSSL, "$openssl s_client -connect $host:$port $additional < /dev/null 2>&1 |") || 145 | die "unable to open $openssl: $!"; 146 | 147 | while () { 148 | next unless $_ =~ /Certificate chain/; 149 | 150 | while () { 151 | next unless $_ =~ /CN=(.*)/; 152 | ($cn) = split(/\//, $1); 153 | $cn .= "[$host]" if ($cn ne $host); 154 | last; 155 | } 156 | } 157 | } 158 | 159 | if ($daysLeft < 0) { 160 | print "$PROGNAME: CRITICAL - $cn expired " . abs($daysLeft) . " day(s) ago.\n"; 161 | exit $ERRORS{'CRITICAL'}; 162 | } elsif ($daysLeft <= $critical) { 163 | print "$PROGNAME: CRITICAL - only $daysLeft day(s) left for $cn.\n"; 164 | exit $ERRORS{'CRITICAL'}; 165 | } elsif ($daysLeft <= $warning) { 166 | print "$PROGNAME: WARNING - only $daysLeft day(s) left for $cn.\n"; 167 | exit $ERRORS{'WARNING'}; 168 | } elsif ($verbose) { 169 | print "$PROGNAME: $daysLeft day(s) left for $cn.\n"; 170 | } 171 | 172 | exit $ERRORS{'OK'}; 173 | 174 | sub print_help { 175 | print_revision($PROGNAME, "\$Revision: $REVISION \$"); 176 | print "Copyright (c) 2006 David Alden 177 | 178 | Check if an SSL certificate is close to expiring 179 | 180 | "; 181 | 182 | print_usage(); 183 | 184 | print " 185 | -a add the text to the openssl line, used for checking the smtp ssl 186 | certificate with starttls (\"-a '-starttls smtp'\") 187 | -c exit with CRITICAL status if number of days left is less than 188 | -h show this help script 189 | -H check the certificate on the indicated host 190 | -o path to openssl binary 191 | -p check the certificate on the specified port 192 | -w exit with WARNING status if number of days left is less than 193 | -v show the number of days left 194 | -V show version and license information 195 | "; 196 | 197 | support(); 198 | } 199 | 200 | 201 | sub print_usage { 202 | print "Usage: $PROGNAME -H [-p ] [-c :] [-w :]\n"; 203 | return(); 204 | } 205 | -------------------------------------------------------------------------------- /check_ssllabs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Query the ssllabs tests for a site 4 | # (C) 2012-2014 Mark Janssen, Sig-I/O Automatisering 5 | # License: CC-BY-3.0 http://creativecommons.org/licenses/by/3.0/ 6 | 7 | SITE=$1 8 | SERVER=$2 9 | 10 | NSCA=/usr/sbin/send_nsca 11 | NSCACONF=/etc/send_nsca.cfg 12 | NSCASERVER=your.nagios.system 13 | HOSTNAME=`hostname` 14 | 15 | if [ -z ${SERVER} ]; then 16 | URL="https://www.ssllabs.com/ssltest/analyze.html?d=${SITE}" 17 | else 18 | URL="https://www.ssllabs.com/ssltest/analyze.html?d=${SITE}&s=${SERVER}" 19 | fi 20 | 21 | SCORE=`curl -k -s "${URL}" | grep -A1 rating_g | tail -1 | awk '{print $1}' | tr -d '\r\n'` 22 | 23 | OK=3 24 | 25 | if [[ "x${SCORE}" == "xA" ]]; then 26 | OK=0 27 | elif [[ "x${SCORE}" == "xA+" ]]; then 28 | OK=0 29 | elif [[ "x${SCORE}" == "xA-" ]]; then 30 | OK=0 31 | elif [[ "x${SCORE}" == "xB" ]]; then 32 | OK=1 33 | else 34 | OK=2 35 | fi 36 | 37 | echo "${HOSTNAME} ssllabs_${SITE} ${OK} SSLLabs rating for ${SITE} = ${SCORE}" | ${NSCA} -c ${NSCACONF} -H ${NSCASERVER} 38 | -------------------------------------------------------------------------------- /check_system_pp: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Usage: .//check_system_pp 4 | # 5 | # Description: 6 | # This plugin determines whether the server is running properly. It will check the following: 7 | # * Are all required processes running? 8 | # * Are all the required TCP/IP ports open? 9 | # 10 | # Created: 27.01.2006 (FBA) 11 | # 12 | # Changes: 28.01.2006 added yellow check (FBA) 13 | # 29.01.2006 change "px -ef" to "ps -ax" (FBA). Problems with long arguments 14 | # 31.01.2006 added all OK Status with all procs and ports (FBA) 15 | # 15.07.2006 change "ps -ax" to "ps ax" (FBA). Also problems with long arguments under RedHat 3/4 16 | # 17.07.2006 Plugin rewrite and bugfixes (Magnus Glantz) 17 | # 19.07.2006 Removed utils.sh dependency. 18 | # 10.06.2017 Sig-IO: Read PROCLIST and PORTLIST from a directory list 19 | # 20 | ################################################################################## 21 | # 22 | # Processes to check (create an empty file with the name to check in these directories) 23 | PROCLIST_RED_DIR="proc-red" 24 | PROCLIST_YELLOW_DIR="proc-yellow" 25 | 26 | # Ports to check (create an empty file with the portnumer as name in this directory) 27 | PORTLIST_DIR="ports" 28 | 29 | PROCLIST_RED=`ls ${PROCLIST_RED_DIR} | tr '\n' ' '` 30 | PROCLIST_YELLOW=`ls ${PROCLIST_YELLOW_DIR} | tr '\n' ' '` 31 | PORTLIST=`ls ${PORTLIST_DIR}` 32 | 33 | ################################################################################## 34 | 35 | PATH="/usr/bin:/usr/sbin:/bin:/sbin" 36 | 37 | STATE_OK=0 38 | STATE_WARNING=1 39 | STATE_CRITICAL=2 40 | STATE_UNKNOWN=3 41 | STATE_DEPENDENT=4 42 | 43 | print_gpl() { 44 | echo "This program is free software; you can redistribute it and/or modify" 45 | echo "it under the terms of the GNU General Public License as published by" 46 | echo "the Free Software Foundation; either version 2 of the License, or" 47 | echo "(at your option) any later version." 48 | echo "" 49 | echo "This program is distributed in the hope that it will be useful," 50 | echo "but WITHOUT ANY WARRANTY; without even the implied warranty of" 51 | echo "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the" 52 | echo "GNU General Public License for more details." 53 | echo "" 54 | echo "You should have received a copy of the GNU General Public License" 55 | echo "along with this program; if not, write to the Free Software" 56 | echo "Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA" 57 | } 58 | 59 | print_help(){ 60 | echo "" 61 | echo "System process and port check script for Nagios." 62 | echo "Tested on RHE3/4, Fedora 4, Solaris 9" 63 | echo "" 64 | echo "Usage: ./check_system_pp" 65 | echo "Website: http://www.nagiosexchange.org" 66 | echo "" 67 | print_gpl 68 | } 69 | 70 | while test -n "$1" 71 | do 72 | case "$1" in 73 | *) print_help; exit $STATE_OK;; 74 | esac 75 | done 76 | 77 | check_processes_red() 78 | { 79 | PROCESS="0" 80 | ERROR_PROCS="" 81 | for PROC in `echo $PROCLIST_RED`; do 82 | if [ `ps -ef | grep $PROC | grep -v grep | wc -l` -lt 1 ]; then 83 | PROCESS=1 84 | ERROR_PROCS="$ERROR_PROCS""$PROC "; 85 | fi 86 | done 87 | 88 | if [ $PROCESS -eq "1" ]; then 89 | exit_red=$STATE_CRITICAL 90 | elif [ $PROCESS -eq "0" ]; then 91 | exit_red=$STATE_OK 92 | fi 93 | } 94 | 95 | check_processes_yellow() 96 | { 97 | PROCESS="0" 98 | WARNING_PROCS="" 99 | for PROC in `echo $PROCLIST_YELLOW`; do 100 | if [ `ps -ef | grep $PROC | grep -v grep | wc -l` -lt 1 ]; then 101 | PROCESS=1 102 | WARNING_PROCS="$WARNING_PROCS""$PROC "; 103 | fi 104 | done 105 | 106 | if [ $PROCESS -eq "1" ]; then 107 | exit_yellow=$STATE_WARNING 108 | elif [ $PROCESS -eq "0" ]; then 109 | exit_yellow=$STATE_OK 110 | fi 111 | } 112 | 113 | check_ports() 114 | { 115 | PORTS="0" 116 | ERROR_PORTS="" 117 | for NUM in `echo $PORTLIST`; do 118 | if [ `netstat -an | grep LISTEN | grep $NUM | grep -v grep | wc -l` -lt 1 ]; then 119 | PORTS=1 120 | ERROR_PORTS="$ERROR_PORTS""$NUM "; 121 | fi 122 | done 123 | 124 | if [ $PORTS -eq "1" ]; then 125 | exit_ports=$STATE_CRITICAL 126 | elif [ $PORTS -eq "0" ]; then 127 | exit_ports=$STATE_OK 128 | fi 129 | } 130 | 131 | check_processes_red 132 | check_ports 133 | check_processes_yellow 134 | 135 | final_exit=`expr $exit_ports + $exit_red + $exit_yellow` 136 | 137 | if [ $final_exit -eq "0" ]; then 138 | echo "SYSTEM OK - All monitored resources OK. Processes: $PROCLIST_RED $PROCLIST_YELLOW. Ports: $PORTLIST." 139 | exitstatus=$STATE_OK 140 | elif [ $final_exit -eq "1" ]; then 141 | echo "SYSTEM WARNING - Processes DOWN. ($WARNING_PROCS)." 142 | exitstatus=$STATE_WARNING 143 | elif [ $final_exit -ge "1" ]; then 144 | echo "SYSTEM CRITICAL - Resources DOWN! Processes: $ERROR_PROCS $WARNING_PROCS. Ports: $ERROR_PORTS" 145 | exitstatus=$STATE_CRITICAL 146 | fi 147 | 148 | exit $exitstatus 149 | -------------------------------------------------------------------------------- /mon_maria.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | 3 | # Check galera status 4 | # (C) Mark Janssen -- Sig-I/O Automatisering 5 | # 2013/09/10 -- Initial version 6 | # 2017/01/21 -- Put config in variables for release 7 | 8 | use strict; 9 | use DBI; 10 | 11 | # Hostname for Send-NSCA 12 | my $hostname = qx/hostname/; 13 | chomp($hostname); 14 | 15 | # Connect to the database and keep using this connection 16 | my $database = "mysql"; 17 | my $databasehost = "localhost"; 18 | my $databaseport = "3306"; 19 | my $checkuser = "galeracheck"; 20 | my $checkpassword = "replacewithyourpassword"; 21 | my $nagioshost = "nagios.local"; 22 | my $nscaconfig = "/usr/local/etc/send_nsca.cfg"; 23 | my $nscabin = "/usr/sbin/send_nsca"; 24 | my $galeraclustersize = "3"; 25 | 26 | my $dbh; 27 | 28 | # Setup some globals 29 | my $sth; 30 | my $errstring = ""; 31 | my $errcount = 0; 32 | my $loopcount = 0; 33 | my $oldstatus = 0; 34 | my $debug = 1; 35 | 36 | my $downfile = "/tmp/mysql-down"; # Created when a check fails, to be used by keepalived 37 | my $offfile = "/tmp/mysql-off"; # Created manually to force checks to fail, will create $downfile 38 | my $pidfile = "/home/galeramon/mon_maria.pid"; 39 | 40 | sub writepid() 41 | { 42 | open( PID, ">$pidfile" ) or die "Can't open PIDFILE\n"; 43 | printf PID "$$"; 44 | close( PID) ; 45 | } 46 | 47 | sub connectdb() 48 | { 49 | if ( $dbh = DBI->connect("DBI:mysql:$database:$databasehost:$databaseport", $checkuser, $checkpassword ) ) 50 | { 51 | $dbh->{mysql_auto_reconnect} = 1; 52 | } 53 | else 54 | { 55 | $errcount += 2; 56 | $errstring = "Can't connect to database"; 57 | notifynsca(); 58 | exit 2; 59 | } 60 | } 61 | 62 | # Tell Nagios (NSCA) what we found 63 | sub notifynsca() 64 | { 65 | my $status = $errcount; 66 | if ( $status > 2 ) 67 | { 68 | $status = 2; 69 | } 70 | if ( $status == 0 ) 71 | { 72 | $errstring = "OK" 73 | } 74 | 75 | open( NSCA, "|$nscabin -H $nagioshost -c $nscaconfig 2>&1 > /dev/null" ) or die "Can't open NSCA\n"; 76 | printf NSCA "$hostname\tgalera_check\t$status\t$errstring ($loopcount)\n"; 77 | print "$hostname\tgalera_check\t$status\t$errstring\n" if $debug; 78 | close( NSCA) ; 79 | } 80 | 81 | writepid(); 82 | connectdb(); 83 | 84 | # Keep looping through the checks 85 | while( 1 == 1 ) 86 | { 87 | my @result; 88 | # 89 | # CHECK 1: show global status where variable_name="wsrep_local_state" 90 | # 91 | 92 | # Local state should be 4 93 | $sth = $dbh->prepare('show global status where variable_name="wsrep_local_state"'); 94 | if (!$sth) { 95 | $errcount++; 96 | $errstring .= $dbh->errstr . " "; 97 | } 98 | if (!$sth->execute) { 99 | $errcount++; 100 | $errstring .= $dbh->errstr . " "; 101 | } 102 | @result = $sth->fetchrow_array(); 103 | $sth->finish(); 104 | 105 | if ( $result[1] != 4 ) 106 | { 107 | $errcount++; 108 | $errstring .= "Local state not OK "; 109 | } 110 | 111 | # 112 | # CHECK 2: show global variables where variable_name="wsrep_on" 113 | # 114 | 115 | # wsrep_on should be on 116 | $sth = $dbh->prepare('show global variables where variable_name="wsrep_on"'); 117 | if (!$sth) { 118 | $errcount++; 119 | $errstring .= $dbh->errstr . " "; 120 | } 121 | if (!$sth->execute) { 122 | $errcount++; 123 | $errstring .= $dbh->errstr . " "; 124 | } 125 | @result = $sth->fetchrow_array(); 126 | $sth->finish(); 127 | 128 | if ( $result[1] ne 'ON' ) 129 | { 130 | $errcount++; 131 | $errstring .= "WSREP not ON "; 132 | } 133 | 134 | # 135 | # CHECK 3: Cluster size 136 | # 137 | 138 | # wsrep_cluster_size should be 3 ($galeraclustersize) 139 | $sth = $dbh->prepare('select variable_name,variable_value from information_schema.global_status where variable_name = "wsrep_cluster_size"'); 140 | if (!$sth) { 141 | $errcount++; 142 | $errstring .= $dbh->errstr . " "; 143 | } 144 | if (!$sth->execute) { 145 | $errcount++; 146 | $errstring .= $dbh->errstr . " "; 147 | } 148 | @result = $sth->fetchrow_array(); 149 | $sth->finish(); 150 | 151 | if ( $result[1] != '$galeraclustersize' ) 152 | { 153 | $errcount++; 154 | $errstring .= "Cluster size not $galeraclustersize "; 155 | } 156 | 157 | # 158 | # CHECK 4: Override check 159 | # 160 | 161 | if ( -e $offfile ) 162 | { 163 | $errcount++; 164 | $errstring .= "MySQL manually forced off "; 165 | } 166 | else 167 | { 168 | if ( -e $downfile ) 169 | { 170 | unlink $downfile; 171 | } 172 | } 173 | 174 | if ( $errcount != 0 ) 175 | { 176 | # Create downfile, so keepalived knows this node is not working correctly 177 | open(MYSQLDOWN,">$downfile"); 178 | print MYSQLDOWN ""; 179 | close( MYSQLDOWN ); 180 | } 181 | 182 | 183 | # 184 | # After all the checks, report back to nagios if results are different 185 | # or this is the 30th concurrent check with the same results. 186 | # So we always tell nagios at least every 30 runs. 187 | # 188 | 189 | if ( $errcount > 0 ) 190 | { 191 | print "$errcount errors encountered: $errstring\n"; 192 | if ( $oldstatus != $errcount ) 193 | { 194 | notifynsca(); 195 | $loopcount = 0; 196 | } 197 | else 198 | { 199 | $loopcount++; 200 | } 201 | $oldstatus = $errcount; 202 | $errcount = 0; 203 | $errstring = ""; 204 | } 205 | else 206 | { 207 | if ( $oldstatus != $errcount ) 208 | { 209 | notifynsca(); 210 | $loopcount = 0; 211 | } 212 | else 213 | { 214 | $loopcount++; 215 | } 216 | $oldstatus = 0; 217 | } 218 | 219 | if ( ($loopcount % 30) == 0 ) 220 | { 221 | notifynsca(); 222 | } 223 | 224 | # Delay a bit before running again 225 | sleep 1; 226 | } 227 | 228 | # Disconnect from the database... though we should never get here 229 | $dbh->disconnect(); 230 | unlink $pidfile; 231 | -------------------------------------------------------------------------------- /monitor.rc: -------------------------------------------------------------------------------- 1 | NSCA=/usr/sbin/send_nsca 2 | NSCACONF=/etc/nagios/send_nsca.cfg 3 | NSCASERVER=your.nagios.system 4 | NSCAPORT=5667 5 | HOSTNAME=`hostname` 6 | CHECKPATH=/usr/lib64/nagios/plugins 7 | TIMEOUT=10 8 | MQTTHOST=127.0.0.1 9 | MQTTTOPIC="nsca/monitor" 10 | MQTTWARNTOPIC="alert/monitor" 11 | 12 | CHECKS=( 13 | 'check_users|check_users -w 5 -c 10' 14 | 'check_load|check_load -w 15,10,5 -c 30,25,20' 15 | 'check_disk_root|check_disk -w 20% -c 10% -p /' 16 | 'check_zombie_procs|check_procs -w 5 -c 10 -s Z' 17 | 'check_total_procs|check_procs -w 350 -c 500' 18 | 'check_disk|check_disk -w 15% -c 10% -X selinuxfs -X tmpfs -X usbfs -X devpts -X usbfs' 19 | 'check_swap|check_swap -w 40 -c 20' 20 | 'check_ntp_time|check_ntp_time -H pool.ntp.org -w 5 -c 45' 21 | ) 22 | -------------------------------------------------------------------------------- /monitor.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # NRPE-Alternative without active checks 4 | # (C) 2012 Mark Janssen, Sig-I/O Automatisering 5 | # License: CC-BY-3.0 http://creativecommons.org/licenses/by/3.0/ 6 | # 7 | # 2012/10/08: Version 0.5, initial version, published on sig-io.nl 8 | # 2012/12/12: Version 0.6, use mutex from http://wiki.bash-hackers.org/howto/mutex 9 | # 2012/12/12: Version 0.7, use monitor.rc file for host-specific configuration 10 | # 2014/05/01: Version 0.71, send host 'check' result 11 | # 2014/05/26: Version 0.8, optionally publish to mqtt 12 | # 2017/06/10: Version 0.9, ability to specify port for NSCA receiver 13 | 14 | # Run some nagios checks, and report their results using nsca 15 | 16 | # Load settings 17 | . /root/scripts/monitor.rc 18 | 19 | LOCKDIR=/var/run/monitor 20 | PIDFILE=${LOCKDIR}/pid 21 | 22 | if [ -n "$TIMEOUT" ]; 23 | then 24 | PREPEND="/usr/bin/timeout ${TIMEOUT} " 25 | else 26 | PREPEND="" 27 | fi 28 | 29 | # Acquire lock... 30 | if mkdir "${LOCKDIR}" &>/dev/null; then 31 | trap 'ECODE=$?; 32 | rm -rf "${LOCKDIR}"' 0 33 | echo "$$" >"${PIDFILE}" 34 | 35 | # the following handler will exit the script on receiving these signals 36 | # the trap on "0" (EXIT) from above will be triggered by this trap's "exit" command! 37 | trap 'echo "[$0] Killed by a signal." >&2 38 | exit 3' 1 2 3 15 39 | 40 | # Send host check result 41 | echo -e "${HOSTNAME}\t0\tChecked by $0" | ${NSCA} -H ${NSCASERVER} -p ${NSCAPORT} -c ${NSCACONF} > /dev/null 42 | if [ ${MQTTHOST} ]; then 43 | mosquitto_pub -h ${MQTTHOST} -t ${MQTTTOPIC} -m "{'host':'${HOSTNAME}', 'check':'${HOSTNAME}', 'returncode':'0', 'data':'Checked by $0'}" 44 | fi 45 | 46 | # Run actual checks 47 | for CHECK in "${CHECKS[@]}" 48 | do 49 | CHECKNAME=`echo ${CHECK} | awk -F\| '{print $1}'` 50 | CHECKCMD=`echo ${CHECK} | awk -F\| '{print $2}'` 51 | 52 | DATA=`${PREPEND}${CHECKPATH}/${CHECKCMD}` 53 | RETVAL=$? 54 | 55 | echo -e "${HOSTNAME}\t${CHECKNAME}\t${RETVAL}\t${DATA}" | ${NSCA} -H ${NSCASERVER} -p ${NSCAPORT} -c ${NSCACONF} 56 | 57 | if [ ${MQTTHOST} ]; then 58 | mosquitto_pub -h ${MQTTHOST} -t ${MQTTTOPIC} -m "{'host':'${HOSTNAME}', 'check':'${CHECKNAME}', 'returncode':'${RETVAL}', 'data':'${DATA}'}" 59 | if [ ${RETVAL} -ne 0 ]; then 60 | mosquitto_pub -h ${MQTTHOST} -t ${MQTTWARNTOPIC} -m "{'host':'${HOSTNAME}', 'check':'${CHECKNAME}', 'returncode':'${RETVAL}', 'data':'${DATA}'}" 61 | fi 62 | fi 63 | 64 | done > /dev/null 65 | else # lock failed, now check if the other PID is alive 66 | OTHERPID="$(cat "${PIDFILE}")" 67 | 68 | if [ $? != 0 ]; then 69 | echo "lock failed, PID ${OTHERPID} is active" >&2 70 | exit 2 71 | fi 72 | 73 | if ! kill -0 $OTHERPID &>/dev/null; then 74 | # lock is stale, remove it and restart 75 | rm -rf "${LOCKDIR}" 76 | exec "$0" "$@" 77 | else 78 | # lock is valid and OTHERPID is active - exit, we're locked! 79 | exit 2 80 | fi 81 | fi 82 | 83 | -------------------------------------------------------------------------------- /nagios-lvm-space.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | # Check free space in LVM volume-group 4 | # (C) 2012 Mark Janssen, Sig-I/O Automatisering 5 | # License: CC-BY-3.0 http://creativecommons.org/licenses/by/3.0/ 6 | 7 | VOLGROUP=$1 8 | WARNSIZE=200 9 | CRITSIZE=100 10 | CODE=0 11 | TXTCODE="OK" 12 | TXT="Volume group ${VOLGROUP} free-space: " 13 | SEND_NSCA=/usr/sbin/send_nsca 14 | HOSTNAME=`hostname -s` 15 | NSCAHOST=your.nagios.host 16 | NSCA_CONF=/etc/nagios/send_nsca.cfg 17 | 18 | FREE=`/sbin/vgs --noheadings --units=G --nosuffix -o vg_name,vg_free ${VOLGROUP} | awk '{print $2}' | awk -F. '{print $1}'` 19 | 20 | if [ ${FREE} -lt ${WARNSIZE} ]; then 21 | CODE=1 22 | TXTCODE="WARNING" 23 | fi 24 | 25 | if [ ${FREE} -lt ${CRITSIZE} ]; then 26 | CODE=2 27 | TXTCODE="CRITICAL" 28 | fi 29 | 30 | 31 | echo "${HOSTNAME} lvm-free-space ${CODE} ${TXTCODE}: ${TXT} ${FREE}\n" | ${SEND_NSCA} -H ${NSCAHOST} -c ${NSCA_CONF} 2>&1 > /dev/null 32 | exit 0 33 | 34 | -------------------------------------------------------------------------------- /nsca-receive-http.cgi: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # © 2019 -- Sig-I/O Automatisering -- Mark Janssen 4 | # 2019/06/24: Version 1.0 -- MIT Licensed 5 | 6 | # Process posted NSCA results from send_nsca_http_post, and forward them 7 | # to the nagios.cmd / icinga.cmd socket 8 | 9 | use strict; 10 | use warnings; 11 | use CGI; 12 | use CGI::Carp qw(fatalsToBrowser); 13 | 14 | sub output_top($); 15 | sub output_error($); 16 | sub output_end($); 17 | sub process_data($); 18 | 19 | my $q = new CGI; 20 | 21 | print $q->header(); 22 | output_top($q); 23 | 24 | if ($q->param()) { 25 | process_data($q); 26 | } 27 | 28 | output_end($q); 29 | exit 0; 30 | 31 | # Outputs the start html tag, stylesheet and heading 32 | sub output_top($) { 33 | my ($q) = @_; 34 | print $q->start_html(); 35 | } 36 | 37 | sub output_error($) { 38 | my ($q) = @_; 39 | print $q->div("Access Denied"); 40 | print $q->end_html; 41 | } 42 | 43 | # Outputs a footer line and end html tags 44 | sub output_end($) { 45 | my ($q) = @_; 46 | print $q->end_html; 47 | } 48 | 49 | # Displays the results of the form 50 | sub process_data($) { 51 | my ($q) = @_; 52 | 53 | my $hname = $q->param('hostname'); 54 | my $cname = $q->param('checkname'); 55 | my $res = $q->param('retval'); 56 | my $edata = $q->param('extradata'); 57 | my $now = time(); 58 | 59 | # Limit checks to some specific domain 60 | if ( $hname =~ /some\.subdomain\.tld/ ) 61 | { 62 | open(my $fh, '>>', '/var/lib/icinga/rw/icinga.cmd'); 63 | print $fh "[$now] PROCESS_SERVICE_CHECK_RESULT;$hname;$cname;$res;$edata\n"; 64 | close $fh; 65 | } 66 | else 67 | { 68 | output_error($q); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /parse-backupninja-logs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Parse backupninja log-files to report backup-status to nagios-nsca 4 | # (C) 2012 Mark Janssen, Sig-I/O Automatisering 5 | # License: CC-BY-3.0 http://creativecommons.org/licenses/by/3.0/ 6 | 7 | # Check logfiles of backups for last-run time and exit status 8 | # If run without arguments, check all files 9 | # if run with a hostname, only check that specific logfile 10 | 11 | TODAY=`date +"%b %d"` 12 | YESTERDAY=`date -d yesterday +"%b %d"` 13 | WARN=0 14 | WARNTXT="" 15 | SEND_NSCA=/usr/sbin/send_nsca 16 | NSCA_CONF=/etc/send_nsca.cfg 17 | NSCAHOST=your.nagios.host 18 | LOGPATH=/path/to/backupninja/reports 19 | 20 | cd ${LOGPATH} 21 | 22 | if [[ $# -eq '0' ]]; then 23 | FILTER="*.log" 24 | else 25 | if [[ -z $1 ]]; then 26 | FILTER="*.log" 27 | else 28 | case "$1" in 29 | somehost | someotherhost ) 30 | echo "OK: Backups for host $1 are disabled" 31 | exit 0; 32 | ;; 33 | esac 34 | FILTER=$1.log 35 | fi 36 | fi 37 | 38 | for file in ${FILTER} 39 | do 40 | host=`basename $file .log` 41 | if [[ "$host" != "backupninja" ]]; then 42 | data=`grep "finished action" $file | tail -n1` 43 | timestamp=`echo $data | awk '{print $1,$2,$3}'` 44 | datum=`echo $data | awk '{print $1,$2}'` 45 | state=`echo $data | awk '{print $9}'` 46 | 47 | if [[ ( "$datum" != "$TODAY" ) && ( "$datum" != "$YESTERDAY" ) ]]; then 48 | WARNTXT="${WARNTXT}Backup of host: $host is STALE (date: $timestamp) " 49 | let WARN=$WARN+1 50 | echo "$host ninjabackup 1 Backup is STALE ($timestamp)\n" | ${SEND_NSCA} -H ${NSCAHOST} -c ${NSCA_CONF} 2>&1 > /dev/null 51 | elif [[ "$state" != "SUCCESS" ]]; then 52 | WARNTXT="${WARNTXT}Backup of host: $host finished at '$timestamp' with state '$state' " 53 | echo "$host ninjabackup 2 Backup ${state}\n" | ${SEND_NSCA} -H ${NSCAHOST} -c ${NSCA_CONF} 2>&1 > /dev/null 54 | let WARN=$WARN+1 55 | else 56 | echo "$host ninjabackup 0 Backup ${state}\n" | ${SEND_NSCA} -H ${NSCAHOST} -c ${NSCA_CONF} 2>&1 > /dev/null 57 | 58 | fi 59 | fi 60 | done 61 | 62 | if [[ "$WARN" -eq 0 ]]; then 63 | echo "All backups completed OK" 64 | exit 0; 65 | else 66 | echo "${WARN} backup messages: ${WARNTXT}" 67 | exit 2; 68 | fi 69 | 70 | echo "WARNING, end of script reached" 71 | exit 1; 72 | 73 | -------------------------------------------------------------------------------- /reset_ssllabs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Clear the ssllabs cache for a site, run max 1x per day 4 | # (C) 2012 Mark Janssen, Sig-I/O Automatisering 5 | # License: Public Domain 6 | 7 | curl -k -o /dev/null -s https://www.ssllabs.com/ssltest/clearCache.html?d=$1 8 | sleep 5 9 | curl -k -o /dev/null -s https://www.ssllabs.com/ssltest/analyze.html?d=$1 10 | -------------------------------------------------------------------------------- /send_nsca_http.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | use strict; 3 | use warnings; 4 | use LWP::UserAgent; 5 | 6 | # © 2019 -- Sig-I/O Automatisering -- Mark Janssen 7 | # 2019/06/24: Version 1.0 -- MIT Licensed 8 | 9 | # Drop-in replacement for send_nsca, takes check results from stdin 10 | # seperated by tabs (like normal send_nsca), and submit them as http-post 11 | # fields to the specified URL 12 | # Use nsca-receive-http.cgi (also in this repo) to process the results 13 | 14 | # Change this to the URL of our nsca-receive-http.cgi 15 | my $url = 'https://hostname/nsca/post.cgi'; 16 | my $ua = LWP::UserAgent->new(); 17 | 18 | while () 19 | { 20 | chomp; 21 | my ($hostname, $checkname, $retval, $data) = split('\t', $_); 22 | 23 | my %form; 24 | $form{'hostname'}=$hostname; 25 | $form{'checkname'}=$checkname; 26 | $form{'retval'}=$retval; 27 | $form{'extradata'}=$data; 28 | 29 | my $response = $ua->post( $url, \%form ); 30 | my $content = $response->as_string(); 31 | 32 | print $content; 33 | } 34 | -------------------------------------------------------------------------------- /split-hotfolder.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Function: Split files in specified hotfolder into various queues 4 | # Mark Janssen -- Sig-I/O Automatisering -- 2018/02/08 5 | 6 | ARGS=$# 7 | 8 | if [ $# -lt 3 ]; then 9 | echo "illegal number of parameters" 10 | echo "Usage: $0 [ ] ..." 11 | echo "\tminimal 2 outputs" 12 | exit 1; 13 | fi 14 | 15 | # First argument is source location directory 16 | INPUT=$1 17 | 18 | # Additional directories (at least 2) are destination paths to devide over 19 | shift 20 | declare -a OUTPUTS=($*) 21 | NROUT=${#OUTPUTS[@]} 22 | 23 | FILENUM=0 24 | for file in ${INPUT}/* 25 | do 26 | let "OUTMOD=$FILENUM%$NROUT" 27 | # echo "Found file '$file' (filenum: $FILENUM)" 28 | # echo "Moving file to output $OUTMOD, which is: ${OUTPUTS[$OUTMOD]}" 29 | mv -v "$file" "${OUTPUTS[$OUTMOD]}" 30 | ((FILENUM++)) 31 | done 32 | -------------------------------------------------------------------------------- /ygrep: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | import yaml 5 | import argparse 6 | import fnmatch 7 | 8 | # CC-Zero, this code was generated by AI 9 | # Flatten a bunch of yaml dicts and lists, and grep for a matching key 10 | 11 | 12 | def flatten_yaml(data, parent_key='', result=None, list_key='name'): 13 | """ 14 | Recursively flatten a nested YAML structure into key-value pairs. 15 | If lists are encountered, replace indices with a value from list_key if available. 16 | 17 | Args: 18 | data (any): The current level of the YAML data. 19 | parent_key (str): The key path leading to this level. 20 | result (dict): The flattened result dictionary. 21 | list_key (str): The key to use as the name for list items. 22 | 23 | Returns: 24 | dict: A dictionary of flattened key-value pairs. 25 | """ 26 | if result is None: 27 | result = {} 28 | 29 | if isinstance(data, dict): 30 | for key, value in data.items(): 31 | new_key = f"{parent_key}.{key}" if parent_key else key 32 | flatten_yaml(value, new_key, result, list_key) 33 | elif isinstance(data, list): 34 | for item in data: 35 | if isinstance(item, dict) and list_key in item: 36 | item_name = item[list_key] 37 | new_key = f"{parent_key}.['{item_name}']" 38 | else: 39 | item_name = str(data.index(item)) 40 | new_key = f"{parent_key}.[{item_name}]" 41 | flatten_yaml(item, new_key, result, list_key) 42 | else: 43 | result[parent_key] = data 44 | 45 | return result 46 | 47 | 48 | def search_yaml_files(search_key, paths='.', list_key='name'): 49 | """ 50 | Search for a specific key pattern in all YAML files under a directory. 51 | 52 | Args: 53 | search_key (str): The key path pattern to search for. 54 | paths (list): The directories to search in. 55 | list_key (str): The key to use for naming list items. 56 | """ 57 | for base_dir in paths: 58 | for root, _, files in os.walk(base_dir): 59 | for file in files: 60 | if file.endswith(('.yaml', '.yml')): 61 | file_path = os.path.join(root, file) 62 | try: 63 | with open(file_path, "r") as f: 64 | data = yaml.safe_load(f) 65 | if data: 66 | flattened = flatten_yaml(data, list_key=list_key) 67 | for key, value in flattened.items(): 68 | if fnmatch.fnmatch(key, search_key): 69 | print(f"{file_path}: {key} = {value}") 70 | except Exception as e: 71 | print(f"Error reading {file_path}: {e}") 72 | 73 | 74 | def main(): 75 | parser = argparse.ArgumentParser( 76 | description="Search YAML files for a specific flattened key pattern.") 77 | parser.add_argument("search_key", help="The key path pattern to search for (e.g., 'some.dict.[*].with.lists').") 78 | parser.add_argument("paths", nargs="*", default=".", help="The directories to search in.") 79 | parser.add_argument("--list-key", default="name", help="The key used to name list items (default: 'name').") 80 | args = parser.parse_args() 81 | 82 | search_yaml_files(args.search_key, args.paths, args.list_key) 83 | 84 | 85 | if __name__ == "__main__": 86 | main() 87 | --------------------------------------------------------------------------------