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
|
#!perl
#
# This plugin takes a mountpoint and checks that a filesystem is mounted
# thereupon, once and once only.
#
# Author: Tom Ryder <tom@sanctum.geek.nz>
# License: MIT
#
package main;
# Force me to write this properly
use strict;
use warnings;
use utf8;
# Require at least this Perl version
use 5.010_001;
# Import required modules
use English qw(-no_match_vars);
use Exception::Class ( PluginException => { alias => 'throw' } );
use Monitoring::Plugin qw(%ERRORS);
use Path::Tiny;
use Quota;
use Try::Tiny;
# Decree package version
our $VERSION = '1.01';
# Add description and license package variables
our $DESCRIPTION = <<'EOF';
This plugin takes a mountpoint and checks that a filesystem is mounted
thereupon, once and once only.
EOF
our $LICENSE = <<'EOF';
MIT License <https://opensource.org/licenses/MIT>
EOF
# Custom plugin options
our @OPTS = (
{
spec => 'mountpoint|m=s',
help => 'Path to mountpoint',
label => 'PATH',
required => 1,
},
);
# Build Monitoring::Plugin object
my $mp = Monitoring::Plugin->new(
usage => 'Usage: %s --mountpoint|-m PATH',
version => $VERSION,
blurb => $DESCRIPTION,
license => $LICENSE,
);
# Anything that dies in here raises ->plugin_die()
try {
# Add and read custom options
for my $opt (@OPTS) {
$mp->add_arg( %{$opt} );
}
$mp->getopts();
# Start counting down to timeout
alarm $mp->opts->timeout();
# Get a cleaned-up and absolute path for the mountpoint
length $mp->opts->mountpoint
or throw 'Empty mountpoint path';
my $point = path( $mp->opts->mountpoint )->realpath();
$point->exists()
or throw "$point does not exist";
$point->is_dir()
or throw "$point is not a directory";
# Read the mount table row by row and collect any entries that correspond
# to our mountpoint
my @mounts = grep { $_->{path} eq $point } mounts();
# Make a string for the message that describes the device and type for each
# of the matching mounts, comma-separated
my $devs = join q(, ), map { "$_->{dev} ($_->{type})" } @mounts;
# One mount is ideal; exit OK, describing the mounted devices and the
# filesytem types
if ( @mounts == 1 ) {
$mp->add_message( $ERRORS{OK}, "Mounted on $point: $devs\n" );
}
# More than one mount is not ideal; exit WARNING, describing the mounted
# devices and the filesystem types
elsif ( @mounts > 1 ) {
$mp->add_message( $ERRORS{WARNING}, "Multi mounts on $point: $devs\n" );
}
# No matching mount at all is bad
else {
$mp->add_message( $ERRORS{CRITICAL}, "No mounts found on $point\n" );
}
# Exit with the selected code and message
$mp->plugin_exit( $mp->check_messages );
}
catch {
$mp->plugin_die($_);
};
# Return a listref of hashrefs describing every mount table entry
sub mounts {
# Open mount table for reading, throw on error (return great than zero)
Quota::setmntent() == 0
or throw Quota::strerr();
# Iterate through each mount table entry to collect a list. The
# getmntent() function here returns an empty list when it's read the whole
# table, and undef on error in place of what would normally be the device,
# so this may seem a bit awkward on first reading.
#
my @mounts;
while ( my @mnt = Quota::getmntent() ) {
# Check the first element; if it's undefined, there was an error, and
# we should bail out
defined $mnt[0]
or throw Quota::strerr();
# Otherwise, this really is a mountpoint entry; extract the device,
# mountpoint, and filesystem type
my ( $dev, $path, $type ) = @mnt;
length $path or next;
# Build a hash structure including canonicalising and resolving the
# path, and add it as a reference to the mounts collection
my %mount = (
dev => $dev || 'unknown',
path => path($path)->realpath(),
type => $type || 'unknown',
);
push @mounts, \%mount;
}
# Close mount table
Quota::endmntent();
# Return collected mounts
return @mounts;
}
1;
|