#!/usr/bin/perl -w use strict; use warnings; use Cwd 'abs_path'; sub prtmsg; # doesn't pick up offline swap partitions # deal with unexpected problems. $SIG{__DIE__} = sub { print "@_"; exit 3; }; my $mount; my $fstab; my (%mounted_disks, %mounted_disks_options, %fstab_disks, %fstab_disks_options); # store the read details. my (@ignore, $ign); my $ignore_file = "/usr/local/nagios/etc/mount_ignore"; my $os = `uname`; chomp $os; if ($os eq 'Linux') { $mount = "/bin/mount"; $fstab = "/etc/fstab"; } elsif ($os eq 'SunOS') { $mount = "/usr/sbin/mount"; $fstab = "/etc/vfstab"; } else { die "Unknown OS: $os"; } ## read the list of ignore prefixes if present if (open( my $ignore_fh, $ignore_file)) { while (<$ignore_fh>) { chomp; push @ignore, $_; } close $ignore_fh; } ######################################################## # get the device and mount point from fstab (what should be mounted) ######################################################## open( my $fstab_fh, $fstab) || die "Failed to open $fstab: $!"; while ( <$fstab_fh> ) { chomp; s/^\s+//; s/#.*$//; s/\s+$//; next if $_ eq ''; my ($device, $mount_point, $opts); ($device, $mount_point, $opts) = (split(/\s+/, $_))[0, 1, 3] if $os eq 'Linux'; ($device, $mount_point, $opts) = (split(/\s+/, $_))[0, 2, 5] if $os eq 'SunOS'; ### print "$device $mount_point $opts\n"; $device = abs_path("/dev/disk/by-uuid/" . readlink "/dev/disk/by-uuid/$1") if $device =~ m/UUID=(.*)/; next unless $device =~ m!/! and $mount_point =~ m!/!; # drop swap, etc. partitions $mount_point =~ s#/$## unless $mount_point =~ m#^/$#; next if $device =~ m!(^/dev/cdrom)|(^/dev/fd\d+)!; next if $os eq 'Linux' and $opts =~ /noauto/; next if $os eq 'SunOS' and $opts !~ /yes/; next if grep m#^$mount_point$#, @ignore; $fstab_disks{$mount_point} = $device; $fstab_disks_options{$mount_point} = [ split /,/, $opts ]; #print "%%%$device%%%%\n"; #print join "\n", @{$fstab_disks_options{$mount_point}}; #print "\n\n"; } close $fstab_fh; ### my $i; ### foreach $i (keys %fstab_disks) {print "$i\n";} $fstab_disks{"/"} = "/" if $os eq 'SunOS'; ## root isn't in vfstab for solaris ######################################################## # get the device and mount point of the mounted disks ######################################################## open( my $mount_fh, "$mount |") || die "Failed to open $mount: $!"; while ( <$mount_fh> ) { my ($device, $mount_point, $mopt); ($device, $mount_point, $mopt) = (split(/\s+/, $_))[0,2,5] if $os eq 'Linux'; ($device, $mount_point) = (split(/\s+/, $_))[2,0] if $os eq 'SunOS'; next unless $device =~ m!/!; ## ignore pseudo-fs next if grep m#^$mount_point$#, @ignore; ### print "$device $mount_point\n"; $mounted_disks{$mount_point} = $device; $mopt =~ s#[\(\)]##g; $mounted_disks_options{$mount_point} = [ split /,/, $mopt ]; #print "%%%$device%%%%\n"; #print join "\n", @{$mounted_disks_options{$mount_point}}; #print "\n\n"; } close $mount_fh; ######################################################## # find inconsistant disks ######################################################## my @not_mounted = sort grep { ! exists $mounted_disks{$_} } keys %fstab_disks; my @not_persistent = sort grep { ! exists $fstab_disks{$_} } keys %mounted_disks; my (@ro_mts, @fstab_ro_mts); foreach (keys %mounted_disks) { #print "###$_###:\n"; #print "Mount##", join ",,,", @{$mounted_disks_options{$_}}, "##\n"; #print "Fstab##", join ",,,", @{$fstab_disks_options{$_}}, "##\n"; grep (/^ro$/, @{$mounted_disks_options{$_}}) && ! grep (/^ro$/, @{$fstab_disks_options{$_}}) and push @ro_mts, $_; grep (/^ro$/, @{$fstab_disks_options{$_}}) && (! grep (/^ro$/, @{$mounted_disks_options{$_}}) || grep (/^rw$/, @{$mounted_disks_options{$_}})) and push @fstab_ro_mts, $_; } #print join "%%%%", @fstab_ro_mts; ######################################################## # Build output ######################################################## my %out = ( '0' => 'OK: All disks are mounted correctly and persistent', '1' => 'WARNING: ', '2' => 'CRITICAL: ', ); my $message = ""; my $exit_code = 0; @fstab_ro_mts > 0 and do { $message = prtmsg \@fstab_ro_mts, " should be mounted read only (and it's not!)
\n", " should be mounted read only (and they are not!)
\n"; $exit_code = 1; }; @not_persistent > 0 and do { $message .= prtmsg \@not_persistent, " is not persistent
\n", " are not persistent
\n"; $exit_code = 1; }; @not_mounted > 0 and do { $message .= prtmsg \@not_mounted, " is not mounted
\n", " are not mounted
\n"; $exit_code = 2; }; @ro_mts > 0 and do { $message .= prtmsg \@ro_mts, " is mounted read only (and it shouldn't be!)", " are all mounted read only (and they shouldn't be!)"; $exit_code = 2; }; print $out{$exit_code} . "$message\n"; exit $exit_code; sub prtmsg { my $arr = shift; my $msgsingle = shift; my $msgplural = shift; if (@$arr == 1) { return "@$arr" . $msgsingle; } else { return join (", ", @$arr) . $msgplural; } }