|
| 1 | +#!python |
| 2 | +"""Nagios plugin to check number of logged in users.""" |
| 3 | + |
| 4 | +import argparse |
| 5 | +import logging |
| 6 | +import nagiosplugin |
| 7 | +import subprocess |
| 8 | + |
| 9 | +_log = logging.getLogger('nagiosplugin') |
| 10 | + |
| 11 | + |
| 12 | +class Users(nagiosplugin.Resource): |
| 13 | + """Domain model: system logins. |
| 14 | +
|
| 15 | + The `Users` class is a model of system aspects relevant for this |
| 16 | + check. It determines the logged in users and counts them. |
| 17 | + """ |
| 18 | + |
| 19 | + who_cmd = 'who' |
| 20 | + |
| 21 | + def __init__(self): |
| 22 | + self.users = [] |
| 23 | + self.unique_users = set() |
| 24 | + |
| 25 | + def list_users(self): |
| 26 | + """Return list of logged in users. |
| 27 | +
|
| 28 | + The user list is determined by invoking an external command |
| 29 | + defined in `who_cmd` (default: who) and parsing its output. The |
| 30 | + command is expected to produce one line per user with the user |
| 31 | + name at the beginning. |
| 32 | + """ |
| 33 | + _log.info('querying users with "%s" command', self.who_cmd) |
| 34 | + users = [] |
| 35 | + try: |
| 36 | + p = subprocess.Popen([self.who_cmd], stdout=subprocess.PIPE, |
| 37 | + stdin=subprocess.PIPE) |
| 38 | + for line in p.communicate()[0].splitlines(): |
| 39 | + _log.debug('who output: %s', line.strip()) |
| 40 | + users.append(line.split()[0].decode()) |
| 41 | + except OSError: |
| 42 | + raise nagiosplugin.CheckError( |
| 43 | + 'cannot determine number of users ({0} failed)'.format( |
| 44 | + self.who_cmd)) |
| 45 | + return users |
| 46 | + |
| 47 | + def probe(self): |
| 48 | + """Create check metric for user counts. |
| 49 | +
|
| 50 | + This method returns two metrics: `total` is total number of user |
| 51 | + logins including users with multiple logins. `unique` counts |
| 52 | + only unique user id. This means that users with multiple logins |
| 53 | + are only counted once. |
| 54 | + """ |
| 55 | + self.users = self.list_users() |
| 56 | + self.unique_users = set(self.users) |
| 57 | + return [nagiosplugin.Metric('total', len(self.users), min=0), |
| 58 | + nagiosplugin.Metric('unique', len(self.unique_users), min=0)] |
| 59 | + |
| 60 | + |
| 61 | +class UsersSummary(nagiosplugin.Summary): |
| 62 | + """Create status line and long output. |
| 63 | +
|
| 64 | + For the status line, the text snippets created by the contexts work |
| 65 | + quite well, so leave `ok` and `problem` with their default |
| 66 | + implementations. For the long output (-v) we wish to display *which* |
| 67 | + users are actually logged in. Note how we use the `resource` |
| 68 | + attribute in the resuls object to grab this piece of information |
| 69 | + from the domain model object. |
| 70 | + """ |
| 71 | + |
| 72 | + def verbose(self, results): |
| 73 | + super(UsersSummary, self).verbose(results) |
| 74 | + if 'total' in results: |
| 75 | + return 'users: ' + ', '.join(results['total'].resource.users) |
| 76 | + |
| 77 | + |
| 78 | +@nagiosplugin.guarded |
| 79 | +def main(): |
| 80 | + argp = argparse.ArgumentParser() |
| 81 | + argp.add_argument('-w', '--warning', metavar='RANGE', |
| 82 | + help='warning if total user count is outside RANGE'), |
| 83 | + argp.add_argument('-c', '--critical', metavar='RANGE', |
| 84 | + help='critical is total user count is outside RANGE') |
| 85 | + argp.add_argument('-W', '--warning-unique', metavar='RANGE', |
| 86 | + help='warning if unique user count is outside RANGE') |
| 87 | + argp.add_argument('-C', '--critical-unique', metavar='RANGE', |
| 88 | + help='critical if unique user count is outside RANGE') |
| 89 | + argp.add_argument('-v', '--verbose', action='count', default=0, |
| 90 | + help='increase output verbosity (use up to 3 times)') |
| 91 | + argp.add_argument('-t', '--timeout', default=10, |
| 92 | + help='abort execution after TIMEOUT seconds') |
| 93 | + args = argp.parse_args() |
| 94 | + check = nagiosplugin.Check( |
| 95 | + Users(), |
| 96 | + nagiosplugin.ScalarContext('total', args.warning, args.critical, |
| 97 | + fmt_metric='{value} users logged in'), |
| 98 | + nagiosplugin.ScalarContext( |
| 99 | + 'unique', args.warning_unique, args.critical_unique, |
| 100 | + fmt_metric='{value} unique users logged in'), |
| 101 | + UsersSummary()) |
| 102 | + check.main(args.verbose, args.timeout) |
| 103 | + |
| 104 | + |
| 105 | +if __name__ == '__main__': |
| 106 | + main() |
0 commit comments