1#!/bin/sh
2
3# ########################################################################
4# This program is part of $PROJECT_NAME$
5# License: GPL License (see COPYING)
6# Authors:
7#  Baron Schwartz
8# Depends-on: pt-deadlock-logger
9# ########################################################################
10
11# ########################################################################
12# Redirect STDERR to STDOUT; Nagios doesn't handle STDERR.
13# ########################################################################
14exec 2>&1
15
16# ########################################################################
17# Set up constants, etc.
18# ########################################################################
19STATE_OK=0
20STATE_OK=0
21STATE_WARNING=1
22STATE_CRITICAL=2
23STATE_UNKNOWN=3
24STATE_DEPENDENT=4
25
26# ########################################################################
27# Run the program.
28# ########################################################################
29main() {
30   # Get options
31   for o; do
32      case "${o}" in
33         -c)              shift; OPT_CRIT="${1}"; shift; ;;
34         --defaults-file) shift; OPT_DEFT="${1}"; shift; ;;
35         -H)              shift; OPT_HOST="${1}"; shift; ;;
36         -i)              shift; OPT_INTERVAL="${1}"; shift; ;;
37         -l)              shift; OPT_USER="${1}"; shift; ;;
38         -L)              shift; OPT_LOPA="${1}"; shift; ;;
39         -p)              shift; OPT_PASS="${1}"; shift; ;;
40         -P)              shift; OPT_PORT="${1}"; shift; ;;
41         -S)              shift; OPT_SOCK="${1}"; shift; ;;
42         -T)              shift; OPT_TABLE="${1}";  shift; ;;
43         -w)              shift; OPT_WARN="${1}"; shift; ;;
44         --version)       grep -A2 '^=head1 VERSION' "$0" | tail -n1; exit 0 ;;
45         --help)          perl -00 -ne 'm/^  Usage:/ && print' "$0"; exit 0 ;;
46         -*)              echo "Unknown option ${o}.  Try --help."; exit 1; ;;
47      esac
48   done
49   OPT_WARN=${OPT_WARN:-12}
50   OPT_CRIT=${OPT_CRIT:-60}
51   OPT_INTERVAL=${OPT_INTERVAL:-1}
52   OPT_TABLE="${OPT_TABLE:-percona.deadlocks}"
53   if [ -e '/usr/local/etc/nagios/mysql.cnf' ]; then
54      OPT_DEFT="${OPT_DEFT:-/usr/local/etc/nagios/mysql.cnf}"
55   fi
56   if is_not_sourced; then
57      if [ -n "$1" ]; then
58         echo "WARN spurious command-line options: $@"
59         exit 1
60      fi
61   fi
62
63   LEVEL=$(mysql_exec "SELECT COUNT(*) FROM ${OPT_TABLE} WHERE server IN ('${OPT_HOST}', @@hostname) AND ts >= NOW() - INTERVAL ${OPT_INTERVAL}*60 SECOND")
64   if [ $? = 0 ]; then
65      NOTE="${LEVEL:-UNKNOWN} deadlocks in last ${OPT_INTERVAL} minutes"
66      if [ "${LEVEL:-0}" -gt "${OPT_CRIT}" ]; then
67         NOTE="CRIT $NOTE"
68      elif [ "${LEVEL:-0}" -gt "${OPT_WARN}" ]; then
69         NOTE="WARN $NOTE"
70      else
71         NOTE="OK $NOTE"
72      fi
73
74      # Build the common perf data output for graph trending
75      PERFDATA="deadlocks=${LEVEL:-0};${OPT_WARN};${OPT_CRIT};0;"
76      NOTE="$NOTE | $PERFDATA"
77   else
78      NOTE="UNK could not count deadlocks"
79   fi
80   echo $NOTE
81}
82
83# ########################################################################
84# Execute a MySQL command.
85# ########################################################################
86mysql_exec() {
87   mysql ${OPT_DEFT:+--defaults-file="${OPT_DEFT}"} ${OPT_HOST:+-h"${OPT_HOST}"} ${OPT_USER:+-u"${OPT_USER}"} \
88      ${OPT_PASS:+-p"${OPT_PASS}"} ${OPT_SOCK:+-S"${OPT_SOCK}"} ${OPT_PORT:+-P"${OPT_PORT}"} \
89      ${OPT_LOPA:+--login-path="${OPT_LOPA}"} -ss -e "$1"
90}
91
92# ########################################################################
93# Determine whether this program is being executed directly, or sourced/included
94# from another file.
95# ########################################################################
96is_not_sourced() {
97   [ "${0##*/}" = "pmp-check-mysql-deadlocks" ] || [ "${0##*/}" = "bash" -a "$_" = "$0" ]
98}
99
100# ########################################################################
101# Execute the program if it was not included from another file.
102# This makes it possible to include without executing, and thus test.
103# ########################################################################
104if is_not_sourced; then
105   OUTPUT=$(main "$@")
106   EXITSTATUS=$STATE_UNKNOWN
107   case "${OUTPUT}" in
108      UNK*)  EXITSTATUS=$STATE_UNKNOWN;  ;;
109      OK*)   EXITSTATUS=$STATE_OK;       ;;
110      WARN*) EXITSTATUS=$STATE_WARNING;  ;;
111      CRIT*) EXITSTATUS=$STATE_CRITICAL; ;;
112   esac
113   echo "${OUTPUT}"
114   exit $EXITSTATUS
115fi
116
117# ############################################################################
118# Documentation
119# ############################################################################
120: <<'DOCUMENTATION'
121=pod
122
123=head1 NAME
124
125pmp-check-mysql-deadlocks - Alert when pt-deadlock-logger has recorded too many recent deadlocks.
126
127=head1 SYNOPSIS
128
129  Usage: pmp-check-mysql-deadlocks [OPTIONS]
130  Options:
131    -c CRIT         Critical threshold; default 60.
132    --defaults-file FILE Only read mysql options from the given file.
133                    Defaults to /usr/local/etc/nagios/mysql.cnf if it exists.
134    -H HOST         MySQL hostname.
135    -i INTERVAL     Interval over which to count, in minutes; default 1.
136    -l USER         MySQL username.
137    -L LOGIN-PATH   Use login-path to access MySQL (with MySQL client 5.6).
138    -p PASS         MySQL password.
139    -P PORT         MySQL port.
140    -S SOCKET       MySQL socket file.
141    -T TABLE        The database.table that pt-deadlock-logger uses; default percona.deadlocks.
142    -w WARN         Warning threshold; default 12.
143    --help          Print help and exit.
144    --version       Print version and exit.
145  Options must be given as --option value, not --option=value or -Ovalue.
146  Use perldoc to read embedded documentation with more details.
147
148=head1 DESCRIPTION
149
150This Nagios plugin looks at the table that pt-deadlock-logger (part of Percona
151Toolkit) maintains, and when there have been too many recent deadlocks, it
152alerts.
153
154=head1 PRIVILEGES
155
156This plugin executes the following commands against MySQL:
157
158=over
159
160=item *
161
162C<SELECT> from the C<pt-deadlock-logger> table.
163
164=back
165
166This plugin executes no UNIX commands that may need special privileges.
167
168=head1 COPYRIGHT, LICENSE, AND WARRANTY
169
170This program is copyright 2012-$CURRENT_YEAR$ Baron Schwartz, 2012-$CURRENT_YEAR$ Percona Inc.
171Feedback and improvements are welcome.
172
173THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
174WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
175MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
176
177This program is free software; you can redistribute it and/or modify it under
178the terms of the GNU General Public License as published by the Free Software
179Foundation, version 2.  You should have received a copy of the GNU General
180Public License along with this program; if not, write to the Free Software
181Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
182
183=head1 VERSION
184
185$PROJECT_NAME$ pmp-check-mysql-deadlocks $VERSION$
186
187=cut
188
189DOCUMENTATION
190