-
Notifications
You must be signed in to change notification settings - Fork 7
/
check.autoincrement
executable file
·211 lines (160 loc) · 5.5 KB
/
check.autoincrement
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
#!/usr/bin/env perl
use 5.010;
use strict;
use warnings;
use utf8;
use DBI;
use Getopt::Long;
binmode STDOUT, ':encoding(UTF-8)';
our $VERSION = 3;
GetOptions(
'verbosity=i' => \(my $verbosity),
'critical=f' => \(my $critical),
'warning=f' => \(my $warning),
'dbhost=s' => \(my $dbhost),
'dbuser=s' => \(my $dbuser),
'dbpass=s' => \(my $dbpass),
'configfile=s' => \(my $configfile),
);
my %config;
if ($configfile) {
open my $IN, '<:encoding(UTF-8)', $configfile
or die "Cannot open '$configfile' for reading: $!";
while (<$IN>) {
chomp;
next unless /\S/;
next if /^\s*#/;
if (/^\s*(\w+)\s*=\s*(\S(?:.*\S)?)\s*\z/) {
$config{$1} = $2;
}
else {
die qq[Cannot parse line "$_" in config file "$configfile" (should be: key=value)\n];
}
}
}
$verbosity //= $config{verbosity} // 0;
$warning //= $config{warning} // 0.7;
$critical //= $config{critical} // 0.85;
$dbhost //= $config{dbhost} // 'localhost';
$dbuser //= $config{dbuser} // 'root';
$dbpass //= $config{dbpass};
my %max = (
unsigned_bigint => 18446744073709551615,
unsigned_int => 4294967295,
unsigned_integer => 4294967295,
unsigned_smallint => 65535,
unsigned_tinyint => 255,
unsigned_mediumint => 16777215,
signed_bigint => 9223372036854775807,
signed_int => 2147483647,
signed_integer => 2147483647,
signed_smallint => 32767,
signed_tinyint => 127,
signed_mediumint => 8388607,
);
my $dbh = DBI->connect("dbi:mysql:database=mysql;host=$dbhost", $dbuser, $dbpass, {RaiseError => 1});
my $ai = $dbh->prepare(<<SQL);
SELECT c.table_catalog, c.table_schema, c.table_name, c.column_name, c.data_type, t.auto_increment, c.column_type
FROM information_schema.columns AS c
JOIN information_schema.tables AS t
ON c.table_catalog = t.table_catalog
AND c.table_schema = t.table_schema
AND c.table_name = t.table_name
WHERE c.extra LIKE '%auto_increment%'
ORDER BY c.table_catalog, c.table_schema, c.table_name, c.column_name
SQL
$ai->execute;
my $has_warnings = 0;
my $has_critical = 0;
my $db = '';
my $max_record;
while (my ($catalog, $database, $table, $column, $type, $auto_increment, $column_type) = $ai->fetchrow_array) {
next unless defined $auto_increment;
my $type_with_signed = ( $column_type =~ /unsigned/ ) ? "unsigned_$type" : "signed_$type";
my $max = $max{$type_with_signed};
unless ($max) {
if ($verbosity >= 1) {
say "Don't know maximal value for data type $type_with_signed";
}
next;
}
my $fill = $auto_increment / $max;
if ($verbosity >= 2) {
say join "\t", $catalog, $database, $table, $column, $type_with_signed,
$auto_increment, $fill;
}
if ($fill >= $critical) {
$has_critical++;
printf "CRITICAL: %s.%s.%s at %.3f (%d/%d)\n", $database, $table, $column, $fill, $auto_increment, $max;
}
elsif ($fill >= $warning) {
$has_warnings++;
printf "WARNING: %s.%s.%s at %.3f (%d/%d)\n", $database, $table, $column, $fill, $auto_increment, $max;
}
if (!$max_record || $max_record->{fill} <= $fill) {
$max_record = {
database => $database,
table => $table,
column => $column,
value => $auto_increment,
max => $max,
fill => $fill,
};
}
}
$ai->finish;
if (!$has_warnings && !$has_critical && $max_record) {
printf "OK (maximal value: : %s.%s.%s at %.3f (%d/%d))\n", @{$max_record}{qw/database table column fill value max/};
}
if ($has_critical) {
exit 2;
}
elsif ($has_warnings) {
exit 1;
}
else {
exit 0;
}
__END__
=encoding UTF-8
=head1 NAME
check.autoincrement -- Check if mysql auto_increment columns are close to reaching overflow
=head1 SYNOPSIS
check.autoincrement --configfile=check-ai.conf
Where check-ai.conf has the following format:
dbhost=hostname
dbuser=root
dbpass=verysecret
critical=0.85
warning=0.7
verbosity=0
=head1 DESCRIPTION
This script is intended for nrpe/nagios checks. It checks if auto_increment columns in mysql
databases are approaching the maximal value, and warns if the output value exceeds the
C<warning> or even C<critical> threshold values, which can be configured.
If the C<critical> threshold is exceeded by at least one column, the exit code is 2;
otherwise, if the C<warning> threshold is execeeded, the exit code is 1.
If everything is fine, the exit code is 0.
=head1 CONFIGURATION
The following configuration variables are available, and can be set either through the
config file, or through command line options.
The config file must be specified with C<--configfile=path/to/file>. The command line always
takes precedence over the config file.
=over
=item dbhost
The hostname of the database server. Defaults to C<localhost>.
=item dbuser
The database user. Defaults to C<root>.
=item dbpass
The password for the dabatabase user. Defaults to no password at all.
=item critical
The threshold above which fill factors are considered critical. Defaults to 0.85.
=item warning
The threshold above which fill factors are considered warnings. Defaults to 0.70.
=item verbosity
A number between 0 and 2 that controls the amount of output produced. Defaults to 0.
=back
=head1 AUTHOR
Moritz Lenz <mlenz@noris.net> for noris network AG, Ticket 15769099.
=cut
# vim: ft=perl sw=4 ts=4 tw=78 expandtab cindent