#!/usr/bin/perl
# vim: ts=2 sts=2 sw=2:et ai:
#
# Usage: check_nfsmounts [ -t nfs timeout ] [ -w ]
# Description: determines whether there are stale NFS mounts on the host.
# Author: Clint Byrum
#
# Copyright 2007 Adicio, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <
#
use utils qw{$TIMEOUT %ERRORS};
use Time::HiRes qw{time alarm};
use Getopt::Long;
use strict;
my $version="1.0";
my $nfs_timeout=$TIMEOUT;
my $nfs_warn=-1;
my $writemode=0;
my $help=0;
sub usage {
print STDERR "NFS UNKNOWN: version $version, check_nfs_client [ --nfs-critical|-c seconds ]\n";
print STDERR " [ --nfs-warning seconds ][ --writemode|-w ]\n";
exit $ERRORS{'UNKNOWN'};
}
if(!GetOptions('nfs-timeout|nfstimeout|critical|c|t=f' => \$nfs_timeout,
'nfs-warning=f' => \$nfs_warn,
'writemode|write|w' => \$writemode,
'help' => \$help,
)) {
&usage;
}
if($help) {
&usage;
}
if($nfs_timeout <= 0) {
print STDERR "timeout must be greater than 0\n";
&usage;
}
our $dir; # Because its a signal handler, we have to
sub alarm_handler {
print "NFS CRITICAL: Stale NFS mount point - $dir.\n";
exit $ERRORS{'CRITICAL'};
}
sub bad_mount {
my $mountpoint=shift();
my $emsg=shift();
print "NFS CRITICAL: cannot operate on mount point $mountpoint. [$emsg]\n";
exit $ERRORS{'CRITICAL'};
}
#my @dirs = `mount | grep " type nfs " | awk '{print \$3}'`;
if(!open MTAB,"< /etc/mtab") {
print "NFS UNKNOWN: could not open mtab.\n";
exit $ERRORS{'UNKNOWN'};
}
my @dirs=();
my %mountmodes=();
while(my $line=<MTAB>) {
if($line =~ /^[^ ]+ [^ ]+ nfs /) {
my @fields=split(/\s+/,$line);
my $mountpoint=$fields[1];
push(@dirs,$mountpoint);
#my %modes=split(/,/,$fields[3]);
my $modes = {};
foreach my $mode (split(/,/,$fields[3])) {
$modes->{$mode}=1;
}
$mountmodes{$mountpoint}=$modes;
}
}
close MTAB;
if(@dirs < 1) {
print "NFS OK: no NFS mounts found.\n";
exit $ERRORS{'OK'};
}
my @ages=();
my @warnings=();
foreach $dir (@dirs) {
chomp $dir;
$SIG{ALRM} = \&alarm_handler;
my $start=time;
my $pid=fork;
if($pid==0) {
chdir $dir or &bad_mount($dir,$!);
if($writemode and exists($mountmodes{$dir}->{"rw"})) {
open X,"> $dir/.nfscheck" or exit $?;
print X $ENV{HOSTNAME}."\n".localtime()."\n"; # XXX Full disk may fail..
close X or exit $?;
}
exit 0;
} else {
alarm $nfs_timeout;
waitpid $pid,0;
if($?) {
&bad_mount($dir,$?);
};
alarm 0;
}
my $age=time()-$start;
if($nfs_warn > 0 and $age > $nfs_warn) {
push(@warnings,sprintf("$dir took %7.5f to complete all operations ",$age));
}
push(@ages,$age);
}
my $x=0;
my $agetot=0;
my $maxage=0;
foreach my $age (@ages) {
$agetot+=$age;
if($age > $maxage) {
$maxage=$age;
}
$x++;
}
my $avgage=$agetot/$x;
my $perfdata=sprintf("maxtime=%9.7f;avgtime=%9.7f;mountpoints=$x",$maxage,$avgage);
if(@warnings) {
print "NFS WARNING: @warnings|$perfdata\n";
exit $ERRORS{'WARNING'};
}
printf "NFS OK: $x mount points avg of %7.5f secs, max %7.5f secs.|$perfdata\n",$avgage,$maxage,$maxage,$avgage;
exit $ERRORS{'OK'};
|