This file is indexed.

/usr/share/check_mk/checks/mknotifyd is in check-mk-server 1.2.8p16-1ubuntu0.1.

This file is owned by root:root, with mode 0o755.

The actual contents of the file can be viewed below.

  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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
#!/usr/bin/python
# -*- encoding: utf-8; py-indent-offset: 4 -*-
# +------------------------------------------------------------------+
# |             ____ _               _        __  __ _  __           |
# |            / ___| |__   ___  ___| | __   |  \/  | |/ /           |
# |           | |   | "_ \ / _ \/ __| |/ /   | |\/| | " /            |
# |           | |___| | | |  __/ (__|   <    | |  | | . \            |
# |            \____|_| |_|\___|\___|_|\_\___|_|  |_|_|\_\           |
# |                                                                  |
# | Copyright Mathias Kettner 2014             mk@mathias-kettner.de |
# +------------------------------------------------------------------+
#
# This file is part of Check_MK.
# The official homepage is at http://mathias-kettner.de/check_mk.
#
# check_mk 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 in version 2.  check_mk is  distributed
# in the hope that it will be useful, but WITHOUT ANY WARRANTY;  with-
# out even the implied warranty of  MERCHANTABILITY  or  FITNESS FOR A
# PARTICULAR PURPOSE. See the  GNU General Public License for more de-
# tails. You should have  received  a copy of the  GNU  General Public
# License along with GNU Make; see the file  COPYING.  If  not,  write
# to the Free Software Foundation, Inc., 51 Franklin St,  Fifth Floor,
# Boston, MA 02110-1301 USA.

# Example output from agent:
# <<<mknotifyd:sep(0)>>>
# [mysite]
# Version:         1.2.7i1
# Updated:         1425389753 (2015-03-03 14:35:53)
# Started:         1425388950 (2015-03-03 14:22:30, 803 sec ago)
# Configuration:   1425388950 (2015-03-03 14:22:30, 803 sec ago)
# Listening FD:    4
#
# Spool:           New
# Count:           0
# Oldest:
#
# Spool:           Deferred
# Count:           0
# Oldest:
#
# Spool:           Corrupted
# Count:           4
# Oldest:          1425305956 (2015-03-02 15:19:16, 83797 sec ago)
#
# Connection:      127.0.0.1:46906
# Type:            incoming
# State:           established
# Since:           1425389490 (2015-03-03 14:31:30, 263 sec ago)
# Socket FD:       5
# HB. Interval:    10 sec
# LastHeartbeat:   1425389750 (2015-03-03 14:35:50, 3 sec ago)
# InputBuffer:     0 Bytes
# OutputBuffer:    0 Bytes

def parse_mknotifyd(info):
    parsed = {}
    for line in info:
        if line[0].startswith('['):
            site = line[0][1:-1]
            site_entry = {
                "spools"      : {},
                "connections" : {},
            }
            sub_entry = site_entry
            parsed[site] = site_entry
        else:
            varname, value = line[0].split(":", 1)
            value = value.strip()
            if varname == "Spool":
                sub_entry = {}
                site_entry["spools"][value] = sub_entry

            elif varname == "Connection":
                sub_entry = {}
                site_entry["connections"][value] = sub_entry

            else:
                if value == "None":
                    value = None
                elif value and varname not in [
                    "Type", "State", "Version", "Status Message",
                    "Pending Acknowledgements", "Connect Time" ]:
                    value = int(value.split()[0])
                elif varname == "Connect Time":
                    value = float(value.split()[0])
                sub_entry[varname] = value

    # Fixup names of the connections. For incoming connections the remote
    # port is irrelevant. It changes randomly. But there might anyway be
    # more than one connection from the same remote host, so we are forced
    # to create artificial numbers if that is the case
    for site_name, stats in parsed.items():
        remote_addresses = {}
        for connection_name, connection in stats["connections"].items():
            if connection["Type"] == "incoming":
                remote_address = connection_name.split(":")[0]
                remote_addresses.setdefault(remote_address, []).append(connection)
                del stats["connections"][connection_name]

        for address, connections in remote_addresses.items():
            if len(connections) == 1:
                stats["connections"][address] = connection
            else:
                for nr, connection in enumerate(connections):
                    stats["connections"][address + "/" + str(nr+1)] = connection

    return parsed


#.
#   .--Spooler Status------------------------------------------------------.
#   | ____                    _             ____  _        _               |
#   |/ ___| _ __   ___   ___ | | ___ _ __  / ___|| |_ __ _| |_ _   _ ___   |
#   |\___ \| '_ \ / _ \ / _ \| |/ _ \ '__| \___ \| __/ _` | __| | | / __|  |
#   | ___) | |_) | (_) | (_) | |  __/ |     ___) | || (_| | |_| |_| \__ \  |
#   ||____/| .__/ \___/ \___/|_|\___|_|    |____/ \__\__,_|\__|\__,_|___/  |
#   |      |_|                                                             |
#   +----------------------------------------------------------------------+
#   |                                                                      |
#   '----------------------------------------------------------------------'

def inventory_mknotifyd(parsed):
    return [ (p, {}) for p in parsed ]

def check_mknotifyd(item, _no_params, parsed):
    if item not in parsed:
        yield 2, "No status information, Spooler not running"
        return

    now = time.time()
    stat = parsed[item]
    version = stat["Version"]

    # Output Version
    yield 0, "Version: " + version

    # Check age of status file. It's updated every 20 seconds
    status_age = now - stat["Updated"]
    if status_age > 90:
        yield 2, "Status last updated %s ago, spooler seems crashed or busy" % get_age_human_readable(status_age)
    else:
        yield 0, "Spooler running"

    # Are there any corrupted files
    corrupted = stat["spools"]["Corrupted"]
    if corrupted["Count"]:
        yield 1, "%d corrupted files: youngest %s ago" % (corrupted["Count"], get_age_human_readable(now - corrupted["Youngest"]))

    # Are there deferred files that are too old?
    deferred = stat["spools"]["Deferred"]
    if deferred["Count"]:
        age = now - deferred["Oldest"]
        count = deferred["Count"]
        if age > 5:
            state = 1
        elif age > 600:
            state = 2
        else:
            state = 0
        yield state, "%d deferred files: oldest %s ago" % (count, get_age_human_readable(age))

    return

check_info["mknotifyd"] = {
    "parse_function"      : parse_mknotifyd,
    "inventory_function"  : inventory_mknotifyd,
    "check_function"      : check_mknotifyd,
    "service_description" : "Notification Spooler %s",
}



#.
#   .--Connections---------------------------------------------------------.
#   |        ____                            _   _                         |
#   |       / ___|___  _ __  _ __   ___  ___| |_(_) ___  _ __  ___         |
#   |      | |   / _ \| '_ \| '_ \ / _ \/ __| __| |/ _ \| '_ \/ __|        |
#   |      | |__| (_) | | | | | | |  __/ (__| |_| | (_) | | | \__ \        |
#   |       \____\___/|_| |_|_| |_|\___|\___|\__|_|\___/|_| |_|___/        |
#   |                                                                      |
#   '----------------------------------------------------------------------'

def inventory_mknotifyd_connection(parsed):
    for site_name, stats in parsed.items():
        for connection_name in stats["connections"]:
            yield site_name + "-" + connection_name, {}


def check_mknotifyd_connection(item, _no_params, parsed):
    states = {
        "established" : (0, "Alive"),
        "cooldown"    : (2, "Connection failed or terminated"),
        "initial"     : (1, "Initialized"),
        "connecting"  : (2, "Trying to connect"),
    }

    site_name, connection_name = item.split('-', 1)
    if site_name not in parsed:
        raise MKCounterWrapped("No status information about spooler available")

    if connection_name in parsed[site_name]["connections"]:
        connection = parsed[site_name]["connections"][connection_name]

        # First check state
        state, state_name = states[connection["State"]]
        yield state, state_name

        if "Status Message" in connection:
            yield 0, connection["Status Message"]

        # Show uptime
        if connection["State"] == "established":
            now = time.time()
            age = now - connection["Since"]
            yield 0, "Uptime: %s" % get_age_human_readable(age)

            if "Connect Time" in connection:
                yield 0, "Connect time: %.3f sec" % connection["Connect Time"]

        # Stats
        for what in ( "Sent", "Received" ):
            num = connection["Notifications " + what]
            if num:
                yield 0, "%d Notifications %s" % (num, what.lower())



check_info["mknotifyd.connection"] = {
    "inventory_function"  : inventory_mknotifyd_connection,
    "check_function"      : check_mknotifyd_connection,
    "service_description" : "Notification Connection %s",
}