├── .gitignore ├── LICENSE.txt ├── Makefile ├── README.md ├── check-systemd-service └── contrib ├── build.sh ├── monitoring-check-systemd-service.spec └── version.sh /.gitignore: -------------------------------------------------------------------------------- 1 | SPECS/* 2 | SOURCES/* 3 | BUILD/* 4 | BUILDROOT/* 5 | RPMS/* 6 | SRPMS/* 7 | 8 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (C) 2016 Pengutronix, Fridolin Tux 2 | 3 | Permission to use, copy, modify, and/or distribute this software 4 | for any purpose with or without fee is hereby granted. 5 | 6 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 7 | WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 8 | WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 9 | AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 10 | CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS 11 | OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 12 | NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PREFIX?=/usr 2 | 3 | # an empty make target as there is nothing todo 4 | build: 5 | 6 | install: 7 | install -d $(DESTDIR)$(PREFIX)/lib/nagios/plugins/ 8 | install check-systemd-service $(DESTDIR)$(PREFIX)/lib/nagios/plugins/check_systemd_service 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Whats this and why? 2 | 3 | This script is intended for icinga/nagios/icinga2 to check the state of a 4 | systemd service. We check the ServiceState and the Substate. 5 | 6 | This tools uses dbus to gather needed informations, as systemd-developer 7 | Lennart Poettering says it is the right way to do and cli output is not stable and should not be parsed. 8 | 9 | https://github.com/systemd/systemd/issues/83 10 | 11 | ## How to install? 12 | 13 | ### Debian 14 | git clone https://github.com/pengutronix/monitoring-check-systemd-service.git 15 | apt-get install python3-nagiosplugin python3-gi 16 | 17 | ### RedHat / CentOS 18 | python 3.6 and the corresponding gobject implementation are provided by the 19 | EPEL package. Follow [the instructions](https://fedoraproject.org/wiki/EPEL) 20 | to install EPEL on your system. The python3-nagiosplugin can be found at 21 | [https://github.com/joernott/python-nagiosplugin-rpm](https://github.com/joernott/python-nagiosplugin-rpm) 22 | and the RPM for this plugin can be built using the instructions below. 23 | 24 | yum -y install rh-python36 python36-gobject python36-gobject-base python3-nagiosplugin nagios-plugin-systemd-service 25 | 26 | ## How to build the RPM 27 | [Set up your RPMBUILD environment](https://wiki.centos.org/HowTos/SetupRpmBuildEnvironment) 28 | and put the SPEC file into the SPECS folder. Then get the source and run rpmbuild: 29 | 30 | curl -o SPECS https://https://raw.githubusercontent.com/joernott/monitoring-check-systemd-service/master/contrib/check-systemd-service.spec 31 | spectool -g -R SPECS/check-systemd-service.spec 32 | rpmbuild -ba SPECS/check-systemd-service.spec 33 | 34 | ## How to use? 35 | 36 | > ./check-systemd-service -h 37 | usage: check-systemd-service [-h] [-v] [-t TIMEOUT] unit 38 | 39 | Nagios plugin to check a systemd service on different properties 40 | 41 | positional arguments: 42 | unit Check this Unit 43 | 44 | optional arguments: 45 | -h, --help show this help message and exit 46 | -v, --verbose increase output verbosity (use up to 3 times) 47 | -t TIMEOUT, --timeout TIMEOUT 48 | abort execution after TIMEOUT seconds 49 | 50 | 51 | > ./check-systemd-service -t 3 systemd-logind 52 | SYSTEMD SERVICE SYSTEMD-LOGIND OK - ServiceState is active(running) 53 | 54 | 55 | ## optional features (future) 56 | 57 | It could check for every systemd service property. The plugin has access to the whole systemd-dbus dataset without parsing any CLI output. 58 | 59 | 60 | -------------------------------------------------------------------------------- /check-systemd-service: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # -*- coding: utf-8 -*- 3 | 4 | """Nagios plugin to check a systemd service on different properties""" 5 | 6 | import argparse 7 | import logging 8 | import collections 9 | import re 10 | 11 | try: 12 | import nagiosplugin 13 | except ImportError as e: 14 | print("Please install python3-nagiosplugin") 15 | raise e 16 | 17 | try: 18 | from gi.repository.Gio import DBusProxy, BusType 19 | except ImportError as e: 20 | print("Please install python3-gi") 21 | raise e 22 | 23 | _log = logging.getLogger('nagiosplugin') 24 | 25 | class Systemd: 26 | """Systemd access""" 27 | 28 | __dbus = None 29 | @classmethod 30 | def dbus(cls): 31 | if not Systemd.__dbus: 32 | _log.debug('Connecting to systemd DBUS') 33 | Systemd.__dbus = DBusProxy.new_for_bus_sync(BusType.SYSTEM, 34 | 0, 35 | None, 36 | 'org.freedesktop.systemd1', 37 | '/org/freedesktop/systemd1', 38 | 'org.freedesktop.systemd1.Manager', 39 | None) 40 | return Systemd.__dbus 41 | 42 | __all_units = None 43 | 44 | @classmethod 45 | def all_units(cls, filter=None): 46 | if not Systemd.__all_units: 47 | _log.debug('Listing all units') 48 | Systemd.__all_units = Systemd.dbus().ListUnits() 49 | units_set = set() 50 | for (name, _, _, _, _, _, _, _, _, _) in Systemd.__all_units: 51 | if filter is not None: 52 | if not re.search(filter, name): 53 | continue 54 | units_set.add(name) 55 | return units_set 56 | 57 | class Systemd_Service_State(object): 58 | """State of a Systemd Unit""" 59 | 60 | def connect_systemd(self, unit): 61 | """ initializing systemd dbus connection """ 62 | try: 63 | loadedUnit = Systemd.dbus().LoadUnit('(s)', unit) 64 | except Exception as e: 65 | _log.error(e) 66 | raise e 67 | 68 | dbus_service = DBusProxy.new_for_bus_sync(BusType.SYSTEM, 69 | 0, 70 | None, 71 | 'org.freedesktop.systemd1', 72 | loadedUnit, 73 | 'org.freedesktop.systemd1.Unit', 74 | None) 75 | self.__dbus_unit = dbus_service 76 | 77 | def __init__(self, unit_name): 78 | self.connect_systemd(unit_name) 79 | self.__prop = {} 80 | 81 | def __get_prop(self, name): 82 | """ 83 | Catching properties from dbus 84 | """ 85 | if not (name in self.__prop): 86 | self.__prop[name] = self.__dbus_unit.get_cached_property(name).unpack() 87 | #_log.debug('%r of %r is %r', name, self.id, self.__prop[name]) 88 | return self.__prop[name] 89 | 90 | @property 91 | def id(self): 92 | return self.__get_prop('Id') 93 | 94 | @property 95 | def activestate(self): 96 | """ 97 | ActiveState contains a state value that reflects whether the unit is 98 | currently active or not. The following states are currently defined: 99 | active, reloading, inactive, failed, activating, deactivating. active 100 | indicates that unit is active (obviously...). reloading indicates 101 | that the unit is active and currently reloading its configuration. 102 | inactive indicates that it is inactive and the previous run was 103 | successful or no previous run has taken place yet. failed indicates 104 | that it is inactive and the previous run was not successful (more 105 | information about the reason for this is available on the unit type 106 | specific interfaces, for example for services in the Result property, 107 | see below). activating indicates that the unit has previously been 108 | inactive but is currently in the process of entering an active state. 109 | Conversely deactivating indicates that the unit is currently in the 110 | process of deactivation. 111 | """ 112 | return self.__get_prop('ActiveState') 113 | t = self.service.get_cached_property('ActiveState').unpack() 114 | _log.debug('ServiceState of %r is %r', self.service, t) 115 | return t 116 | 117 | @property 118 | def substate(self): 119 | """ 120 | SubState encodes states of the same state machine that ActiveState 121 | covers, but knows more fine-grained states that are unit-type-specific. 122 | Where ActiveState only covers six high-level states, SubState covers 123 | possibly many more low-level unit-type-specific states that are mapped 124 | to the six high-level states. Note that multiple low-level states might 125 | map to the same high-level state, but not vice versa. Not all 126 | high-level states have low-level counterparts on all unit types. At 127 | this point the low-level states are not documented here, and are more 128 | likely to be extended later on than the common high-level states 129 | explained above. 130 | """ 131 | return self.__get_prop('SubState') 132 | 133 | @property 134 | def loadstate(self): 135 | """ 136 | LoadState of the unit. 137 | """ 138 | return self.__get_prop('LoadState') 139 | 140 | NOT_LOADED = -3 # !loaded/inactive 141 | NOT_LOADED_ERROR = -1 # !loaded/* 142 | FAILED = 0 # loaded/failed 143 | ACTIVE = 1 # loaded/active 144 | INACTIVE_DEAD = 2 # loaded/inactive/dead 145 | INACTIVE_OTHER = -2 # loaded/inactive/* 146 | CHANGING = 3 # loaded/{reloading|activating|deactivating} 147 | UNKNOWN = -5 # * 148 | @property 149 | def value(self): 150 | """ 151 | Value for metric/performance 152 | """ 153 | if self.loadstate != "loaded": 154 | return Systemd_Service_State.NOT_LOADED 155 | else: 156 | ast = self.activestate 157 | if ast == "failed": 158 | return Systemd_Service_State.FAILED 159 | elif ast == "active": 160 | return Systemd_Service_State.ACTIVE 161 | elif ast == "inactive": 162 | if self.substate == "dead": 163 | return Systemd_Service_State.INACTIVE_DEAD 164 | else: 165 | return Systemd_Service_State.INACTIVE_OTHER 166 | elif ast in ['activating', 'deactivating', 'reloading']: 167 | return Systemd_Service_State.CHANGING 168 | else: 169 | return Systemd_Service_State.UNKNOWN 170 | 171 | def str_state(self, metric, context): 172 | word = "but" 173 | if context.nagios_result(metric) == nagiosplugin.Ok: 174 | word = "and" 175 | return "{} {} {} {}({})".format(self.id, self.loadstate, word, self.activestate, self.substate) 176 | 177 | def range(self, metric, context, state_res): 178 | res = context.nagios_result(metric) 179 | if res == state_res: 180 | return self.value 181 | elif res == nagiosplugin.Ok: 182 | return self.value+1 183 | return None 184 | 185 | def warning(self, metric, context): 186 | return self.range(metric, context, nagiosplugin.Warn) 187 | 188 | def critical(self, metric, context): 189 | return self.range(metric, context, nagiosplugin.Critical) 190 | 191 | class Systemd_Service(nagiosplugin.Resource): 192 | """One Systemd Service""" 193 | 194 | def __init__(self, **kwords): 195 | for key, value in kwords.items(): 196 | self.__setattr__(key, value) 197 | 198 | def normalize(self): 199 | if '.' in self.unit: 200 | _log.debug('Found \'.\' in ServiceName %r, so assuming you know what youre asking for', self.unit) 201 | else: 202 | self.unit = self.unit + '.service' 203 | _log.debug('Normalized unitname to check for %r', self.unit) 204 | 205 | def connect_systemd(self): 206 | """ initializing systemd dbus connection """ 207 | try: 208 | loadedUnit = Systemd.dbus().LoadUnit('(s)', self.unit) 209 | except Exception as e: 210 | _log.error(e) 211 | raise e 212 | 213 | service = DBusProxy.new_for_bus_sync(BusType.SYSTEM, 214 | 0, 215 | None, 216 | 'org.freedesktop.systemd1', 217 | loadedUnit, 218 | 'org.freedesktop.systemd1.Unit', 219 | None) 220 | self.service = service 221 | 222 | @property 223 | def name(self): 224 | """formatting the Testname (will be formatted as uppercase letters)""" 225 | return "SYSTEMD SERVICE %s" % (self.unit.split('.service')[0]) 226 | 227 | 228 | def probe(self): 229 | """ Create check metric for Systemd Service""" 230 | self.normalize() 231 | state = Systemd_Service_State(self.unit) 232 | yield Service_Metric(self.unit, state, context='service_state_explicit') 233 | 234 | class Systemd_Services(nagiosplugin.Resource): 235 | """Several Systemd Services""" 236 | 237 | def __init__(self, **kwords): 238 | for key, value in kwords.items(): 239 | self.__setattr__(key, value) 240 | 241 | @property 242 | def name(self): 243 | """formatting the Testname (will be formatted as uppercase letters)""" 244 | return "SYSTEMD SERVICES" 245 | 246 | def services_to_check(self): 247 | """List of systemd services to check. By default, all presents""" 248 | handled_services = {} 249 | list_services = [] 250 | for unit in Systemd.all_units(filter=self.filter): 251 | id_unit = unit 252 | if id_unit in handled_services: 253 | _log.info("Skipping unit %s already handled with %s", unit, handled_services[id_unit]) 254 | continue 255 | handled_services[id_unit] = unit 256 | list_services.append(unit) 257 | #_log.debug("Adding unit %s", unit) 258 | return list_services 259 | 260 | 261 | def probe(self): 262 | """ Create check metric for Systemd Services""" 263 | services = self.services_to_check() 264 | nb_services = len(services) 265 | services_stat = { 266 | 'loaded': 0, 267 | 'masked': 0, 268 | 'not-found': 0, 269 | 'active': 0, 270 | } 271 | yield nagiosplugin.Metric("checked", nb_services) 272 | for unit in services: 273 | #_log.debug("Probing unit %r", unit) 274 | state = Systemd_Service_State(unit) 275 | loadstate = state.loadstate 276 | if not loadstate in services_stat: 277 | raise nagiosplugin.CheckError( 278 | "unknown LoadState '{}' for unit '{}'".format( 279 | loadstate, unit)) 280 | services_stat[loadstate] += 1 281 | if loadstate == 'loaded' and state.activestate == 'active': 282 | services_stat['active'] += 1 283 | yield Service_Metric(unit, state, context='service_state_auto') 284 | for kind in services_stat.keys(): 285 | yield nagiosplugin.Metric(kind, services_stat[kind]) 286 | return [] 287 | 288 | class Service_Metric(nagiosplugin.Metric): 289 | def __init__(self, name, value, **kwords): 290 | self.__service_state = value 291 | super().__init__() 292 | 293 | def replace(self, **attr): 294 | obj = super().replace(**attr); 295 | obj.__service_state = self.service_state 296 | #print ("copying service_state {} from {} to {}".format(self.service_state, id(self), id(obj))) 297 | return obj; 298 | 299 | @property 300 | def value(self): 301 | return self.service_state.value 302 | 303 | @property 304 | def service_state(self): 305 | #print ("getting service_state in {}".format(id(self))) 306 | return self.__service_state 307 | 308 | class Systemd_Context(nagiosplugin.ScalarContext): 309 | @property 310 | def is_service(self): 311 | return False 312 | 313 | class Service_Context(Systemd_Context): 314 | """Abstract class""" 315 | 316 | @property 317 | def is_service(self): 318 | return True 319 | 320 | def nagios_result(self, metric): 321 | state=metric.service_state 322 | # possible Values are: 323 | # nagiosplugin.Ok, 324 | # nagiosplugin.Warn, 325 | # nagiosplugin.Critical, 326 | # nagiosplugin.Unknown 327 | return type(self).resultD[state.value] 328 | 329 | def evaluate(self, metric, resource): 330 | nr = self.nagios_result(metric) 331 | return self.result_cls(nr, metric=metric) 332 | 333 | def performance(self, metric, resource): 334 | return nagiosplugin.Performance(metric.name, metric.value, metric.uom, 335 | metric.service_state.warning(metric, self), 336 | metric.service_state.critical(metric, self), 337 | metric.min, metric.max) 338 | 339 | 340 | class Service_Context_Auto(Service_Context): 341 | resultD = collections.defaultdict( lambda: nagiosplugin.Unknown, 342 | { 343 | Systemd_Service_State.INACTIVE_OTHER: nagiosplugin.Critical, 344 | Systemd_Service_State.NOT_LOADED_ERROR: nagiosplugin.Critical, 345 | Systemd_Service_State.FAILED: nagiosplugin.Critical, 346 | Systemd_Service_State.NOT_LOADED: nagiosplugin.Ok, 347 | Systemd_Service_State.ACTIVE: nagiosplugin.Ok, 348 | Systemd_Service_State.INACTIVE_DEAD: nagiosplugin.Ok, 349 | Systemd_Service_State.CHANGING: nagiosplugin.Warn, 350 | }) 351 | 352 | class Service_Context_Explicit(Service_Context): 353 | resultD = collections.defaultdict( lambda: nagiosplugin.Unknown, 354 | { 355 | Systemd_Service_State.INACTIVE_OTHER: nagiosplugin.Critical, 356 | Systemd_Service_State.NOT_LOADED_ERROR: nagiosplugin.Critical, 357 | Systemd_Service_State.FAILED: nagiosplugin.Critical, 358 | Systemd_Service_State.NOT_LOADED: nagiosplugin.Critical, 359 | Systemd_Service_State.ACTIVE: nagiosplugin.Ok, 360 | Systemd_Service_State.INACTIVE_DEAD: nagiosplugin.Critical, 361 | Systemd_Service_State.CHANGING: nagiosplugin.Warn, 362 | }) 363 | 364 | class Services_Summary(nagiosplugin.Summary): 365 | 366 | def get_stats(self, results): 367 | stats = { 368 | 'ok': 0, 369 | 'warning': 0, 370 | 'critical': 0, 371 | 'unknown': 0, 372 | } 373 | gstats = {} 374 | total = 0 375 | for r in results: 376 | if not r.context.is_service: 377 | gstats[r.metric.name] = r.metric.value 378 | continue 379 | t = r.state.text 380 | if not t in stats: 381 | raise nagiosplugin.CheckError( 382 | "invalid state '{}' in results".format(t)) 383 | stats[t] += 1 384 | total += 1 385 | stats['all'] = total 386 | for k in gstats: 387 | stats[k] = gstats[k] 388 | return stats 389 | 390 | def ok(self, results): 391 | if len(results) == 1: 392 | return '{0}'.format(results[0]) 393 | stats = self.get_stats(results) 394 | return "{0} units ok ({1} actives, {2} inactives, {3} masked, {4} not-found)".format( 395 | stats['ok'], stats['active'], stats['loaded']-stats['active'], stats['masked'], stats['not-found']) 396 | 397 | def problem(self, results): 398 | stats = self.get_stats(results) 399 | fs = results.first_significant 400 | t = fs.state.text 401 | if stats[t] == 1: 402 | return '{0}'.format(fs) 403 | else: 404 | return "{0} {1} units".format(stats[t], t) 405 | 406 | @nagiosplugin.guarded 407 | def main(): 408 | argp = argparse.ArgumentParser(description=__doc__, 409 | formatter_class=argparse.RawTextHelpFormatter, 410 | ) 411 | argp.add_argument('units', help='Check this Unit', nargs='*') 412 | argp.add_argument('-v', '--verbose', action='count', default=0, 413 | help='increase output verbosity (use up to 3 times)') 414 | argp.add_argument('-t', '--timeout', default=10, 415 | help='abort execution after TIMEOUT seconds') 416 | argp.add_argument('-f', '--filter', default='^.*\.service$', 417 | help='regexp for filtering systemd units') 418 | args = argp.parse_args() 419 | if len(args.units) == 1: 420 | check = nagiosplugin.Check( 421 | Systemd_Service(unit=args.units[0],**vars(args)), 422 | Service_Context_Explicit('service_state_explicit', 423 | fmt_metric=lambda m,c: m.service_state.str_state(m, c)), 424 | ) 425 | check.main(args.verbose, args.timeout) 426 | if len(args.units) == 0: 427 | check = nagiosplugin.Check( 428 | Systemd_Services(**vars(args)), 429 | Service_Context_Auto('service_state_auto', 430 | fmt_metric=lambda m,c: m.service_state.str_state(m, c)), 431 | Service_Context_Explicit('service_state_explicit', 432 | fmt_metric=lambda m,c: m.service_state.str_state(m, c)), 433 | Systemd_Context('checked'), 434 | Systemd_Context('masked'), 435 | Systemd_Context('loaded'), 436 | Systemd_Context('active'), 437 | Systemd_Context('not-found'), 438 | Services_Summary(), 439 | ) 440 | #print (Systemd.all_units()) 441 | check.main(args.verbose, args.timeout) 442 | 443 | if __name__ == '__main__': 444 | main() 445 | 446 | 447 | 448 | -------------------------------------------------------------------------------- /contrib/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | SCRIPT_DIR="$( cd "$(dirname "$0")" ; pwd -P )" 3 | LOGLEVEL=5 4 | 5 | source "${SCRIPT_DIR}/version.sh" 6 | 7 | function init() { 8 | LOGLEVEL_TEXT[0]="Panic" 9 | LOGLEVEL_TEXT[1]="Fatal" 10 | LOGLEVEL_TEXT[2]="Error" 11 | LOGLEVEL_TEXT[3]="Warning" 12 | LOGLEVEL_TEXT[4]="Info" 13 | LOGLEVEL_TEXT[5]="Debug" 14 | LOGLEVEL=4 15 | RPMBUILD_DIR="$(dirname "${SCRIPT_DIR}")" 16 | SPECS_DIR="${RPMBUILD_DIR}/SPECS" 17 | RPMS_DIR="${RPMBUILD_DIR}/RPMS" 18 | SRPMS_DIR="${RPMBUILD_DIR}/SRPMS" 19 | BUILD_DIR="${RPMBUILD_DIR}/BUILD" 20 | SOURCES_DIR="${RPMBUILD_DIR}/SOURCES" 21 | 22 | for DIR in "${SPECS_DIR}" "${RPMS_DIR}" "${SRPMS_DIR}" "${BUILD_DIR}" "${SOURCES_DIR}"; do 23 | if [ ! -d "${DIR}" ]; then 24 | echo "$DIR not found. Creating it." 25 | mkdir -p "${DIR}" 26 | fi 27 | done 28 | } 29 | 30 | function log() { 31 | local LEVEL=$1 32 | if [ ${LEVEL} -le ${LOGLEVEL} ]; then 33 | shift 1 34 | local DATE=$(date +"%Y-%m-%d %H:%M:%S") 35 | printf "%s %s %s\n" "${DATE}" "${LOGLEVEL_TEXT[${LEVEL}]}" "$@" 36 | fi 37 | } 38 | 39 | function get_archive() { 40 | local URL="$1" 41 | local APP="$2" 42 | local VERSION="$3" 43 | local TARGET_DIR="$4" 44 | if [ -z "${URL}" ]; then 45 | echo "get_archive: No URL provided" 46 | exit 1 47 | fi 48 | if [ -z "${APP}" ]; then 49 | echo "get_archive: No application provided" 50 | exit 1 51 | fi 52 | if [ -z "${VERSION}" ]; then 53 | echo "get_archive: No version provided" 54 | exit 1 55 | fi 56 | if [ -n "${TARGET_DIR}" ]; then 57 | cd "${TARGET_DIR}" 58 | fi 59 | log 4 "Downloading ${APP}-${VERSION}.tar.gz into ${TARGET_DIR}" 60 | curl -sSkjL "${URL}" -o "${APP}-${VERSION}.tar.gz" 61 | RESULT=$? 62 | local SIZE=$(cat "${APP}-${VERSION}.tar.gz"|wc -c) 63 | if [ $SIZE -le 512 ]; then 64 | # 112 is the size of a tar.gz with an empty file in it, the average bitbucket error is around 150 bytes 65 | log 2 "Download of ${APP}-${VERSION}.tar.gz failed or is damaged: File too small." 66 | exit 1 67 | fi 68 | return ${RESULT} 69 | } 70 | 71 | function build() { 72 | local APP="$1" 73 | local VERSION="$2" 74 | local RELEASE="$3" 75 | local ARCH="$4" 76 | 77 | cp "${SCRIPT_DIR}/${APP}.spec" "${SPECS_DIR}/" 78 | cd "${RPMBUILD_DIR}" 79 | log 4 "Building ${APP} ${VERSION}-${RELEASE}" 80 | rpmbuild --define="_topdir ${RPMBUILD_DIR}" \ 81 | --define="version ${VERSION}" \ 82 | --define="release ${RELEASE}" \ 83 | --define="app ${APP}" \ 84 | --define="arch ${ARCH}" \ 85 | -ba "${SPECS_DIR}/${APP}.spec" 86 | local RESULT=$? 87 | if [ ${RESULT} -ne 0 ]; then 88 | log 2 "Building the RPM failed" 89 | return ${RESULT} 90 | fi 91 | log 4 "${APP} RPM built successfully" 92 | return 0 93 | } 94 | 95 | init 96 | get_archive "${URL}" "${APP}" "${VERSION}" "${SOURCES_DIR}" 97 | if [ $? -ne 0 ]; then 98 | exit 1 99 | fi 100 | build "${APP}" "${VERSION}" "${RELEASE}" "${ARCH}" 101 | exit $? 102 | -------------------------------------------------------------------------------- /contrib/monitoring-check-systemd-service.spec: -------------------------------------------------------------------------------- 1 | Name: monitoring-check-systemd-service 2 | Version: %{version} 3 | Release: %{release}.el%{?rhel} 4 | Epoch: 1 5 | Summary: Nagios/Icinga check for systemd services 6 | AutoReqProv: no 7 | BuildArch: noarch 8 | Source0: https://github.com/joernott/monitoring-check-systemd-service/archive/v%{version}.tar.gz#/monitoring-check-systemd-service-%{version}.tar.gz 9 | License: BSD 10 | URL: https://github.com/joernott/monitoring-check-systemd-service 11 | %if 0%{?rhel} == 8 12 | Requires: python36 13 | Requires: python3-gobject 14 | Requires: python3-nagiosplugin 15 | %else 16 | Requires: rh-python36 17 | Requires: python36-gobject 18 | Requires: python3-nagiosplugin 19 | %endif 20 | 21 | 22 | %description 23 | This script is intended for icinga/nagios/icinga2 to check the state of a 24 | systemd service. We check the ServiceState and the Substate. 25 | 26 | This tools uses dbus to gather needed informations, as systemd-developer 27 | Lennart Poettering says it is the right way to do and cli output is not stable 28 | and should not be parsed. 29 | 30 | %prep 31 | %setup -q monitoring-check-systemd-service-%{version} 32 | 33 | %install 34 | mkdir -p "$RPM_BUILD_ROOT/usr/lib64/nagios/plugins" 35 | cp check-systemd-service "$RPM_BUILD_ROOT/usr/lib64/nagios/plugins/" 36 | 37 | %files 38 | %attr(755,root,root) /usr/lib64/nagios/plugins/check-systemd-service 39 | 40 | %changelog 41 | * Wed Apr 27 2022 Joern Ott 42 | - Standardize builds for plugins 43 | 44 | -------------------------------------------------------------------------------- /contrib/version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # see https://github.com/joernott/monitoring-check-systemd-service/tags 3 | APP="monitoring-check-systemd-service" 4 | VERSION="1.2.0" 5 | RELEASE="1" 6 | URL="https://github.com/joernott/monitoring-check-systemd-service/archive/refs/tags/v${VERSION}.tar.gz" 7 | ARCH="noarch" 8 | --------------------------------------------------------------------------------