Re: Monitoring cyrusimapd
Nic Bernstein <[email protected]>
| Newsgroups | gmane.mail.imap.cyrus |
|---|---|
| Message-ID | <[email protected]> |
On 06/19/2018 10:23 AM, Albert Shih wrote:
> Hi everyone,
>
> I would like to know what kind of monitoring you perform on a cyrus-imapd.
> Beside classic (check_imap, check_disk, check_cpu etc...) do you have any
> special thing to monitor about cyrus-imapd.
>
> For example do you launch any check on each database ? How can I check if the replication work fine ?
>
We use the attached PHP plugin in Icinga to monitor the SNMP OIDs
provided by Cyrus. I haven't tried this with the newer Prometheus-based
system, but it works just fine on 2.5.X systems built with SNMP enabled:
Usage: $argv[0] -H <host> -C <community string> -s <service>
-p <property> -c <crit_range> -w <warn_range> -h -t
<timeout> -d
Required:
-H [STRING|IP]
Hostname or IP address
-s Which service name to check: This may be any service defined in
cyrus.conf on host being checked. For example: imap, imaps,
pop3
lmtp. This is also used as a label for the results.
* Note: To receive a list of services supported by host,
use the
special keyword 'list'.
* Note: Services with special characters in their name, such as
lmtp[v6], must be quoted; i.e. 'lmtp[v6]'.
Options:
-C STRING
SNMP community string (defaults to `public').
-p <property>
Which property to report (and alarm) on (defaults to 'active'):
* forks
* active
* connections
...
Warning & critical thresholds are allowed (scalar or range) for all
checks. This is primarily a process oriented check script. It's useful
to keep an eye on how many of each service's processes are running
versus the configured quantity.
You may want to take a look at issue 1827 on GitHub in regards to SNMP
on Cyrus:
https://github.com/cyrusimap/cyrus-imapd/issues/1827
Please note that this plugin relies upon utils.php by Marcel Kühn & Doug
Warner:
http://doug.warner.fm/nagios-utilsphp-script-for-php-plugins.html
Cheers,
-nic
--
Nic Bernstein [email protected]
Onlight Inc. www.onlight.com
6525 W Bluemound Rd., Ste 24 v. 414.272.4477
Milwaukee, Wisconsin 53213-4073 f. 414.290.0335
----
Cyrus Home Page: http://www.cyrusimap.org/
List Archives/Info: http://lists.andrew.cmu.edu/pipermail/info-cyrus/
To Unsubscribe:
https://lists.andrew.cmu.edu/mailman/listinfo/info-cyrus
check_cyrus.php
(application/x-php, 9.6 KB)
#!/usr/local/bin/php <?php /** * check_cyrus.php * * Nagios plugin to check status of Cyrus IMAP server over SNMP * * See show_usage(), below, for usage information. * * * Please forward any such changes to us for inclusion in future releases. * mailto:<[email protected]> */ /** * Copyright (c) February 7, 2017 * by Nic Bernstein <[email protected]> * for Onlight, Inc. * PO Box 511219 * Milwaukee, WI 53203 * * All rights reserved, except as provided by the following license * information... * * License Information: * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of the Onlight, llc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ require_once 'utils.php'; /** * show_usage() * * Print standard usage instructions and exit */ function show_usage() { global $argv; echo <<<_EOF_ Usage: $argv[0] -H <host> -C <community string> -s <service> -p <property> -c <crit_range> -w <warn_range> -h -t <timeout> -d Required: -H [STRING|IP] Hostname or IP address -s Which service name to check: This may be any service defined in cyrus.conf on host being checked. For example: imap, imaps, pop3 lmtp. This is also used as a label for the results. * Note: To receive a list of services supported by host, use the special keyword 'list'. * Note: Services with special characters in their name, such as lmtp[v6], must be quoted; i.e. 'lmtp[v6]'. Actions: -h show this help -v show version Options: -C STRING SNMP community string (defaults to `public'). -p <property> Which property to report (and alarm) on (defaults to 'active'): * forks * active * connections -c <crit-range> Range which will not result in a CRITICAL status. -w <warn-range> Range which will not result in a WARNING status - Ranges are inclusive and are indicated with colons. When specified as 'min:max' a STATE_OK will be returned if the result is within the indicated range or is equal to the upper or lower bound. A non-OK state will be returned if the result is outside the specified range. - If specified in the order 'max:min' a non-OK state will be returned if the result is within the (inclusive) range. -t Timeout (in seconds, default 10) -d Log debug output to error log _EOF_; echo "\n"; } /** * info * * Log information * * @param string $message The error message to report * @param boolean $echo (optional) Do we echo this message or simply log it? */ function info($message, $echo=TRUE) { if ($echo) echo "$message\n"; syslog(LOG_INFO, $message); } /** * my_exit() * * Exit program with exit status and optional message and performance * data. * * @param integer $exit_status Exit status * @param string $msg (optional) message to write on exit (default empty) * @param unknown $perfdata (optional) */ function my_exit($exit_status, $msg='', $perfdata='') { global $exit_code; $alert = $exit_code[$exit_status]; $result = empty($msg) ? $alert : "$alert: $msg"; $result = empty($perfdata) ? $result : "$result | $perfdata"; info($result); exit($exit_status); } /** * my_unknown() * * Print message and exit with status 3 (UNKNOWN) * * @param string $msg message to write on exit (default empty) */ function my_unknown($msg='') { global $service; my_exit(STATE_UNKNOWN, "$service UNKNOWN - $msg"); } /******** END OF FUNCTIONS ********/ /******** DECLARE CONSTANTS AND DEFAULTS ********/ define('THIS_VERSION','1.0'); //error_reporting(E_ALL); /* Exit code display strings */ $exit_code = array(STATE_OK => 'OK', STATE_WARNING => 'WARNING', STATE_CRITICAL => 'CRITICAL', STATE_UNKNOWN => 'UNKNOWN', STATE_DEPENDENT => 'DEPENDENT', ); /** * OIDs * * Note: We use numeric OID rather than * `CYRUS-MASTER-MIB::' in case the MIB is not installed. */ define('cyrusMasterInfoUptime', '.1.3.6.1.4.1.3.6.1.1.3.0'); define('serviceName', '.1.3.6.1.4.1.3.6.1.2.1.3'); define('serviceBase', '.1.3.6.1.4.1.3.6.1.2.1.'); $serviceStats = array('forks' => serviceBase . 1, 'active' => serviceBase . 2, 'connections' => serviceBase . 5, ); // Set some defaults // Timeout for SNMP calls $timeout = 10; // Whether to log debugging info $debug = FALSE; // Which unit number of probe are we to read $unit = 1; // The SNMP community string $comm = 'public'; // All properties we support $props = array('forks', 'active', 'connections'); // The default property we care about $prop = 'active'; // Report version? $ver = FALSE; // Process our command line options $shortopts = 'H:s:p:C:c:w:hdt:v'; $opts = getopt($shortopts); foreach ($opts as $opt => $value) { $val = strtolower($value); switch ($opt) { case 'H': // hostname or IP address $host = $value; break; case 'h': // Help show_usage(); my_exit(0); break; case 's': // Service $service = $val; break; case 'p': // Property if (in_array($val, $props)) { $prop = $val; } else { show_usage(); my_exit(STATE_UNKNOWN, "Unknown property '$val' specified"); } break; case 'C': // SNMP community string $comm = $value; break; case 'c': $crit = new Nagios_Plugin_Range($val); break; case 'w': $warn = new Nagios_Plugin_Range($val); break; case 'd': $debug = TRUE; break; case 'v': $msg = "Version: " . THIS_VERSION; $ver = TRUE; break; case 't': $timeout = $value; break; } } // Simply report the version and exit if ($ver) { my_exit(STATE_OK, $msg); } // Make sure we have the barest minimum of settings if ($argc == 0) { show_usage(); my_exit(STATE_UNKNOWN, "No arguments specified"); } if (!isset($host) || empty($host)) { show_usage(); my_exit(STATE_UNKNOWN, "Hostname must be specified"); } if (!isset($service) || empty($service)) { show_usage(); my_exit(STATE_UNKNOWN, "Service must be specified"); } $timeout = $timeout * 1000000; // Timeout is in microseconds snmp_set_valueretrieval(SNMP_VALUE_PLAIN); // Get the process uptime if (($result = snmp2_get($host, $comm, cyrusMasterInfoUptime, $timeout)) === FALSE) { my_unknown("SNMP failed to retrieve data from host $host"); } $days = intval($result / 8640000); $result = $result - ($days * 8640000); $hours = intval($result / 360000); $result = $result - ($hours * 360000); $min = intval($result / 6000); $result = $result - ($min * 6000); $sec = intval($result / 100); $uptime = sprintf("%d:%02d:%02d:%02d", $days, $hours, $min, $sec); // Walk the hosts serviceName table to see what's available if (($result = snmp2_real_walk($host, $comm, serviceName, $timeout)) === FALSE) { my_unknown("SNMP failed to retrieve data from host $host"); } if ($service == 'list') { // Just furnish a list of reported services my_exit(STATE_OK, "Host $host up $uptime reports services " . implode(',', $result)); } // Determine the index of our service foreach ($result as $oid => $oval) { if ($oval == $service) { $index = substr($oid, -1); break; } } if (!isset($index)) { my_exit(STATE_UNKNOWN, "Service '$service' not reported by host $host"); } $perfdata = "$service="; // Get the rest of the values for this service foreach ($serviceStats as $stat => $soid) { if (($result = snmp2_get($host, $comm, "$soid.$index", $timeout)) === FALSE) { my_unknown("SNMP failed to retrieve data from host $host"); } $stats[$stat] = $result; // Prepend a semicolon to datum, if it's not the first if (substr($perfdata, -1) == '=') { $perfdata .= $result; } else { $perfdata .= ";$result"; } } $states = array( 'warn' => STATE_WARNING, 'crit' => STATE_CRITICAL); // Check crit first, so we raise the higher alert foreach (array('crit', 'warn') as $cond) { if (isset($$cond) && $$cond->check_range($stats[$prop])) { $alert = sprintf('%s=%d(out of range)', $prop, $stats[$prop]); my_exit($states[$cond], "$service $uptime $alert", $perfdata); } } // We're okay my_exit(STATE_OK, "$service $uptime $prop=$stats[$prop]", $perfdata); ?> <?php //vim:set ts=2 sw=2 ai: ?>