Last active
November 7, 2017 07:40
-
-
Save sguter90/81c4a639dfcfe272a651e985a5ef2e2e to your computer and use it in GitHub Desktop.
check_disk_inodes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/perl | |
=head1 PLUGIN | |
check_disk_inodes.pl : check inodes of disks on Unix servers | |
=head1 ENVIRONNEMENT | |
Linux | |
=head1 SYNOPSIS | |
./check_disk_inodes.pl [-H <host>] [-w <num>] [-c <num>] [-u <user>] [-p <path>] | |
[-i <dev>] [-f <fs>] [-h] [-C <file>] | |
-h | --help : Display this help | |
-w | --warning : % free inodes to send warning alert (default 10) | |
-c | --critical : % free inodes to send critical alert (default 5) | |
-H | --host : host you want to check by SSH (default localhost) | |
-u | --user : user for SSH connection (default nagios) | |
-i | --ignore : Filesystem you want to ignore | |
format : <name>,<name>,<name>.... | |
-r /pattern/ : include all filesystems matching this regexp | |
-R /pattern/ : exclude all filesystems matching this regexp | |
-f | --filesystem : filesystems or device you have to check (default all) | |
format : <name>:warn:crit,<name>:warn:crit,... | |
unit for warning and critical values is % | |
-C | --conf : specify a configuration file for filesystems threshold | |
definitions | |
-v | --verbose : plugin output contain all FS(default : output shows | |
only warning or critical FS). | |
--srvperf dir : Save datas external files placed on this directory | |
--html : Add <br> in plugin output to improve the Web interface | |
output. | |
-w and -c options allow you to ajust default threshold of all checked fs. | |
Theses values can be overwritten with -C option by specifying a configuration | |
file. perldoc ckech_disk_inodes.pl for more details. | |
If you want to use the SSH connexion and check remote hosts, you must create | |
a connection without password between your nagios server and the checked host | |
(key exchange). | |
=head1 EXAMPLE | |
=head2 No config file for FS : | |
All FS will have the same threshold : | |
not verbose mode : | |
./check_disk_inodes.pl -w 20 -c 10 | |
DISKS OK | |
verbose mode : | |
./check_disk_inodes.pl -w 20 -c 10 -v | |
DISK OK [/dev/shm 145876 (99% free inodes)] [/usr 178974 (56% free inodes)] [/ 220345 (84% | |
free inodes)] [/var 110147 (73% free inodes)] [/tmp 14578 (96% free inodes)] [/home 501 (20% free inodes)] | |
ignore some FS : | |
./check_disk_inodes.pl -i /dev/shm,/tmp,/home -v | |
DISK OK [/usr 178974 (56% free inodes)] [/ 220345 (84% free inodes)] [/var 110147 (73% free inodes)] | |
Specify different threshold : | |
./check_disk_inodes.pl -w 20 -c 10 -f /usr:30:25 -i /dev/shm,/tmp,/home -v | |
=head2 With a FS config file : | |
Syntax (check_disk_inodes.cfg): | |
#FS WARN CRIT | |
/ 4000 3000 | |
/home 200 150 | |
/var 10000 5000 | |
FS threshold are read in this configuration file. the -f option will | |
not be used. | |
./check_disk_inodes.pl -C check_disk_inodes.cfg -i /dev/shm,/tmp,/home | |
DISK WARNING [/ 220345 (84% free inodes)] | |
=cut | |
use Getopt::Long qw(:config no_ignore_case bundling); | |
use Pod::Usage; | |
use strict; | |
my ($opt_c, $opt_w, $opt_h, $opt_i,$opt_f,$opt_s,$opt_u,$opt_H,$opt_C,$opt_v, | |
$opt_html, $opt_srvperf, $opt_r, $opt_R); | |
$opt_u = "nagios"; | |
$opt_i = ""; | |
$opt_w = "10"; | |
$opt_c = "5"; | |
$opt_H = "localhost"; | |
$opt_R = q/^$/; | |
$opt_r = ""; | |
my $exclude_re = "(^//|^none)"; | |
my %alldisks; | |
my %checkdisks; | |
my $diskFreeInodeCmd = "/bin/df -i"; | |
my $output ; | |
my $retour = 'OK'; | |
my %EXIT_CODES = ( | |
'UNKNOWN' => -1, | |
'OK' => 0, | |
'WARNING' => 1, | |
'CRITICAL' => 2 | |
); | |
GetOptions( | |
"h" => \$opt_h, "help" => \$opt_h, | |
"H=s" => \$opt_H, "host=s" => \$opt_H, | |
"w=s" => \$opt_w, "warning=s" => \$opt_w, | |
"c=s" => \$opt_c, "critical=s" => \$opt_c, | |
"u=s" => \$opt_u, "user=s" => \$opt_u, | |
"i=s" => \$opt_i, "ignore=s" => \$opt_i, | |
"f=s" => \$opt_f, "filesystem=s" => \$opt_f, | |
"C=s" => \$opt_C, "conf=s" => \$opt_C, | |
"v" => \$opt_v, "verbose" => \$opt_v, | |
"r=s" => \$opt_r, "R=s" => \$opt_R, | |
"html" => \$opt_html, | |
"srvperf=s" => \$opt_srvperf, | |
) || pod2usage() ; | |
if ($opt_h) { | |
pod2usage(-verbose=>1); | |
exit $EXIT_CODES{'OK'}; | |
} | |
if(!$opt_H) { | |
pod2usage(); | |
exit $EXIT_CODES{'UNKNOWN'}; | |
} | |
my $args; | |
if($opt_H ne "localhost" and $opt_H ne "127.0.0.1") { | |
$diskFreeInodeCmd = "ssh $opt_u\@$opt_H '$diskFreeInodeCmd'"; | |
} | |
my @outputFreeInode = `$diskFreeInodeCmd`; | |
foreach my $l (@outputFreeInode) { | |
if($l =~ /(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\%\s+([\/\w\d\.-]+)$/) { | |
next if ($l =~ m/$opt_R/); | |
next if ($l !~ m/$opt_r/); | |
next if ($l =~ m/$exclude_re/); | |
my ($sumInodes,$usedInodes,$freeInodes,$percentUsedInodes,$disk) = ($1,$2,$3,$4,$5); | |
$alldisks{$disk}->{inode_pused} = $percentUsedInodes; | |
$alldisks{$disk}->{inode_pfree} = 100-$percentUsedInodes; | |
$alldisks{$disk}->{inode_somme} = $sumInodes; | |
$alldisks{$disk}->{inode_used} = $usedInodes; | |
$alldisks{$disk}->{inode_free} = $freeInodes; | |
updateRates($disk,$opt_w,$opt_c,$alldisks{$disk}->{somme}); | |
} | |
} | |
use Data::Dumper; | |
if($opt_f) { | |
my @fs = split(',',$opt_f); | |
foreach my $f (@fs) { | |
# <nom_fs> ou <nom_fs,warn,crit> | |
if($f =~ /^[\/\w\d]+$/) { | |
if(defined($alldisks{$f})) { | |
$checkdisks{$f}=$alldisks{$f}; | |
} | |
} elsif ($f =~ /([\/\w\d]+)\:(\w+)\:(\w+)/) { | |
if(defined($alldisks{$1})) { | |
$checkdisks{$1}=$alldisks{$1}; | |
updateRates($1,$2,$3,$checkdisks{$1}->{somme}); | |
} | |
} else { | |
print "option -f invalide\n"; | |
pod2usage(); | |
exit $EXIT_CODES{'UNKNOWN'}; | |
} | |
} | |
} | |
elsif ($opt_C) { | |
open(FIC,"<$opt_C") or die "$!"; | |
foreach my $l (<FIC>) { | |
if($l =~ /^([\/\w\d]+)\s+(\w+)\s+(\w+)$/) { | |
my ($d,$w,$c)=($1,$2,$3); | |
if(defined($alldisks{$d})) { | |
$checkdisks{$d}=$alldisks{$d}; | |
updateRates($d,$w,$c,$checkdisks{$d}->{somme}); | |
} | |
} | |
} | |
close(FIC); | |
} | |
%checkdisks= (%alldisks, %checkdisks); | |
if($opt_i) { | |
my @fs = split(',',$opt_i); | |
foreach my $f (@fs, "/cdrom", "/mnt/cdrom") { | |
if(defined($checkdisks{$f})) { | |
delete $checkdisks{$f}; | |
} | |
} | |
} | |
my $cmp_warn=0; | |
my $cmp_crit=0; | |
my $perf_data=""; | |
foreach my $f (keys %checkdisks) { | |
if($checkdisks{$f}->{inode_pfree} < $checkdisks{$f}->{critical}) { | |
$cmp_crit++; | |
$output .= "[$f " . $checkdisks{$f}->{inode_free} . | |
" (" . $checkdisks{$f}->{inode_pfree} . '% free inodes)] '; | |
$output .= "<br>" if ($opt_html); | |
} | |
elsif ($checkdisks{$f}->{inode_pfree} < $checkdisks{$f}->{warning}) { | |
$cmp_warn++; | |
$output .= "[$f " . $checkdisks{$f}->{inode_free} . | |
" (" . $checkdisks{$f}->{inode_pfree} . '% free inodes)] '; | |
$output .= "<br>" if ($opt_html); | |
} else { | |
if ($opt_v) { | |
$output .= "[$f " . $checkdisks{$f}->{inode_free} . | |
" (" . $checkdisks{$f}->{inode_pfree} . '% free inodes)] '; | |
$output .= "<br>" if ($opt_html); | |
} | |
} | |
# inodes | |
my $perfwarn=$alldisks{$f}->{inode_somme}*((100-$checkdisks{$f}->{warning})/100); | |
$perfwarn = sprintf("%0.f",$perfwarn); | |
my $perfcrit=$alldisks{$f}->{inode_somme}*((100-$checkdisks{$f}->{critical})/100); | |
$perfcrit = sprintf("%0.f",$perfcrit); | |
$perf_data.="'$f'=$checkdisks{$f}->{inode_used};". | |
"$perfwarn;". | |
"$perfcrit;". | |
"0;". | |
"$checkdisks{$f}->{inode_somme} "; | |
} | |
if($cmp_crit > 0) { | |
$retour='CRITICAL'; | |
} elsif ($cmp_warn > 0) { | |
$retour='WARNING'; | |
} else { | |
$retour='OK'; | |
} | |
#time|machine|service|output|perf | |
if (-d $opt_srvperf) { | |
eval { | |
require Mayday; | |
require Mayday::Config; | |
my $cfg = new Mayday::Config(version => $Mayday::nagios_version, | |
cgi_file => $Mayday::nagios_cgi_cfg) ; | |
die "Can't read nagios configuration" unless $cfg ; | |
my $host = $cfg->get_host_by_address($opt_H) || $opt_H; | |
open(FP, ">>$opt_srvperf/$host.perfdata") ; | |
print FP time(),"|$host|disk|DISK $retour $output|$perf_data\n" ; | |
close(FP) ; | |
} | |
} | |
print "DISK $retour $output|$perf_data\n"; | |
exit $EXIT_CODES{$retour}; | |
########################################################################## | |
sub updateRates { | |
my ($disk,$w,$c,$max) = @_; | |
if($w =~ m/^(\d+)(\D)/) { | |
$alldisks{$disk}->{'warning'} = $alldisks{$disk}->{inode_somme}*((100-$w)/100); | |
} else { | |
$alldisks{$disk}->{'warning'} = $w; | |
} | |
if($c =~ /^(\d+)(\D)/) { | |
$alldisks{$disk}->{'critical'} = $alldisks{$disk}->{inode_somme}*((100-$c)/100); | |
} else { | |
$alldisks{$disk}->{'critical'} = $c; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment