check_systemd 2.1.0__tar.gz → 2.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: check_systemd
3
- Version: 2.1.0
3
+ Version: 2.2.0
4
4
  Summary: Nagios / Icinga monitoring plugin to check systemd for failed units.
5
5
  Home-page: https://github.com/Josef-Friedrich/check_systemd
6
6
  Author: Josef Friedrich
@@ -33,7 +33,8 @@ Description: [![pypi.org](http://img.shields.io/pypi/v/check_systemd.svg)](https
33
33
  ## Command line interface
34
34
 
35
35
  ```
36
- usage: check_systemd [-h] [-c SECONDS] [-e UNIT | -u UNIT] [-v] [-V] [-w SECONDS]
36
+ usage: check_systemd [-h] [-u UNIT | -e UNIT] [-n] [-w SECONDS] [-c SECONDS]
37
+ [-t] [-W SECONDS] [-C SECONDS] [-v] [-V]
37
38
 
38
39
  Copyright (c) 2014-18 Andrea Briganti a.k.a 'Kbyte' <kbytesys@gmail.com>
39
40
  Copyright (c) 2019-20 Josef Friedrich <josef@friedrich.rocks>
@@ -42,17 +43,43 @@ Description: [![pypi.org](http://img.shields.io/pypi/v/check_systemd.svg)](https
42
43
 
43
44
  optional arguments:
44
45
  -h, --help show this help message and exit
45
- -c SECONDS, --critical SECONDS
46
- Startup time in seconds to result in critical status.
47
- -e UNIT, --exclude UNIT
48
- Exclude a systemd unit from the checks. This option can be applied multiple times, for example: -e mnt-data.mount -e
49
- task.service. Regular expressions can be used to exclude multiple units at once, for example: -e 'user@\d+\.service'. For
50
- more informations see the Python documentation about regular expressions (https://docs.python.org/3/library/re.html).
51
46
  -u UNIT, --unit UNIT Name of the systemd unit that is being tested.
47
+ -e UNIT, --exclude UNIT
48
+ Exclude a systemd unit from the checks. This option can
49
+ be applied multiple times, for example: -e mnt-
50
+ data.mount -e task.service. Regular expressions can be
51
+ used to exclude multiple units at once, for example: -e
52
+ 'user@\d+\.service'. For more informations see the
53
+ Python documentation about regular expressions
54
+ (https://docs.python.org/3/library/re.html).
55
+ -n, --no-startup-time
56
+ Don’t check the startup time. Using this option the
57
+ options '-w, --warning' and '-c, --critical' have no
58
+ effect. Performance data about the startup time is
59
+ collected, but no critical, warning etc. states are
60
+ triggered.
61
+ -w SECONDS, --warning SECONDS
62
+ Startup time in seconds to result in a warning status.
63
+ Thedefault is 60 seconds.
64
+ -c SECONDS, --critical SECONDS
65
+ Startup time in seconds to result in a critical status.
66
+ Thedefault is 120 seconds.
67
+ -t, --dead-timers Detect dead / inactive timers. See the corresponding
68
+ options '-W, --dead-timer-warning' and '-C, --dead-
69
+ timers-critical'. Dead timers are detected by parsing
70
+ the output of 'systemctl list-timers'. Dead timer rows
71
+ displaying 'n/a' in the NEXT and LEFTcolumns and the
72
+ time span in the column PASSED exceeds the values
73
+ specified with the options '-W, --dead-timer-warning'
74
+ and '-C, --dead-timers-critical'.
75
+ -W SECONDS, --dead-timers-warning SECONDS
76
+ Time ago in seconds for dead / inactive timers to
77
+ trigger a warning state (by default 6 days).
78
+ -C SECONDS, --dead-timers-critical SECONDS
79
+ Time ago in seconds for dead / inactive timers to
80
+ trigger a critical state (by default 7 days).
52
81
  -v, --verbose Increase output verbosity (use up to 3 times).
53
82
  -V, --version show program's version number and exit
54
- -w SECONDS, --warning SECONDS
55
- Startup time in seconds to result in warning status.
56
83
 
57
84
  Performance data:
58
85
  - count_units
@@ -70,6 +97,32 @@ Description: [![pypi.org](http://img.shields.io/pypi/v/check_systemd.svg)](https
70
97
  * https://exchange.icinga.com/joseffriedrich/check_systemd
71
98
  * https://exchange.nagios.org/directory/Plugins/System-Metrics/Processes/check_systemd/details
72
99
 
100
+ ## Behind the scenes
101
+
102
+ To detect failed units this monitoring script runs:
103
+
104
+ ```sh
105
+ systemctl list-units --all --no-legend
106
+ ```
107
+
108
+ To get the startup time it executes:
109
+
110
+ ```sh
111
+ systemd-analyze
112
+ ```
113
+
114
+ To check a specific unit (`-u, --unit`) this command is executed:
115
+
116
+ ```sh
117
+ systemctl is-active <unit-name>
118
+ ```
119
+
120
+ To find dead timers this plugin launches:
121
+
122
+ ```sh
123
+ systemctl list-timers --all
124
+ ```
125
+
73
126
  ## Testing
74
127
 
75
128
  ```
@@ -0,0 +1,135 @@
1
+ [![pypi.org](http://img.shields.io/pypi/v/check_systemd.svg)](https://pypi.python.org/pypi/check_systemd)
2
+ [![Build Status](https://travis-ci.org/Josef-Friedrich/check_systemd.svg?branch=master)](https://travis-ci.org/Josef-Friedrich/check_systemd)
3
+
4
+ # check_systemd
5
+
6
+ `check_systemd` is a
7
+ [Nagios](https://www.nagios.org) / [Icinga](https://icinga.com)
8
+ monitoring plugin to check [systemd](https://systemd.io) for failed
9
+ units.
10
+
11
+ This Python script will report a degraded system to your monitoring solution.
12
+ It requires only the
13
+ [nagiosplugin](https://nagiosplugin.readthedocs.io/en/stable) library.
14
+
15
+ You can also test a single service with the `-u, --unit` parameter.
16
+
17
+ Released under GNU GPLv2 License.
18
+
19
+ ## Installation
20
+
21
+ ```
22
+ pip3 install check_systemd
23
+ ```
24
+
25
+ ## Command line interface
26
+
27
+ ```
28
+ usage: check_systemd [-h] [-u UNIT | -e UNIT] [-n] [-w SECONDS] [-c SECONDS]
29
+ [-t] [-W SECONDS] [-C SECONDS] [-v] [-V]
30
+
31
+ Copyright (c) 2014-18 Andrea Briganti a.k.a 'Kbyte' <kbytesys@gmail.com>
32
+ Copyright (c) 2019-20 Josef Friedrich <josef@friedrich.rocks>
33
+
34
+ Nagios / Icinga monitoring plugin to check systemd for failed units.
35
+
36
+ optional arguments:
37
+ -h, --help show this help message and exit
38
+ -u UNIT, --unit UNIT Name of the systemd unit that is being tested.
39
+ -e UNIT, --exclude UNIT
40
+ Exclude a systemd unit from the checks. This option can
41
+ be applied multiple times, for example: -e mnt-
42
+ data.mount -e task.service. Regular expressions can be
43
+ used to exclude multiple units at once, for example: -e
44
+ 'user@\d+\.service'. For more informations see the
45
+ Python documentation about regular expressions
46
+ (https://docs.python.org/3/library/re.html).
47
+ -n, --no-startup-time
48
+ Don’t check the startup time. Using this option the
49
+ options '-w, --warning' and '-c, --critical' have no
50
+ effect. Performance data about the startup time is
51
+ collected, but no critical, warning etc. states are
52
+ triggered.
53
+ -w SECONDS, --warning SECONDS
54
+ Startup time in seconds to result in a warning status.
55
+ Thedefault is 60 seconds.
56
+ -c SECONDS, --critical SECONDS
57
+ Startup time in seconds to result in a critical status.
58
+ Thedefault is 120 seconds.
59
+ -t, --dead-timers Detect dead / inactive timers. See the corresponding
60
+ options '-W, --dead-timer-warning' and '-C, --dead-
61
+ timers-critical'. Dead timers are detected by parsing
62
+ the output of 'systemctl list-timers'. Dead timer rows
63
+ displaying 'n/a' in the NEXT and LEFTcolumns and the
64
+ time span in the column PASSED exceeds the values
65
+ specified with the options '-W, --dead-timer-warning'
66
+ and '-C, --dead-timers-critical'.
67
+ -W SECONDS, --dead-timers-warning SECONDS
68
+ Time ago in seconds for dead / inactive timers to
69
+ trigger a warning state (by default 6 days).
70
+ -C SECONDS, --dead-timers-critical SECONDS
71
+ Time ago in seconds for dead / inactive timers to
72
+ trigger a critical state (by default 7 days).
73
+ -v, --verbose Increase output verbosity (use up to 3 times).
74
+ -V, --version show program's version number and exit
75
+
76
+ Performance data:
77
+ - count_units
78
+ - startup_time
79
+ - units_activating
80
+ - units_active
81
+ - units_failed
82
+ - units_inactive
83
+
84
+ ```
85
+
86
+ ## Project pages
87
+
88
+ * https://github.com/Josef-Friedrich/check_systemd
89
+ * https://exchange.icinga.com/joseffriedrich/check_systemd
90
+ * https://exchange.nagios.org/directory/Plugins/System-Metrics/Processes/check_systemd/details
91
+
92
+ ## Behind the scenes
93
+
94
+ To detect failed units this monitoring script runs:
95
+
96
+ ```sh
97
+ systemctl list-units --all --no-legend
98
+ ```
99
+
100
+ To get the startup time it executes:
101
+
102
+ ```sh
103
+ systemd-analyze
104
+ ```
105
+
106
+ To check a specific unit (`-u, --unit`) this command is executed:
107
+
108
+ ```sh
109
+ systemctl is-active <unit-name>
110
+ ```
111
+
112
+ To find dead timers this plugin launches:
113
+
114
+ ```sh
115
+ systemctl list-timers --all
116
+ ```
117
+
118
+ ## Testing
119
+
120
+ ```
121
+ pyenv install 3.7.6
122
+ pyenv install 3.8.1
123
+ pyenv local 3.7.6 3.8.1
124
+ pip3 install tox
125
+ tox
126
+ ```
127
+
128
+ ## Deploying
129
+
130
+ Edit version number in check_systemd.py (without `v`)
131
+
132
+ ```
133
+ git tag v2.0.11
134
+ git push --tags
135
+ ```
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: check-systemd
3
- Version: 2.1.0
3
+ Version: 2.2.0
4
4
  Summary: Nagios / Icinga monitoring plugin to check systemd for failed units.
5
5
  Home-page: https://github.com/Josef-Friedrich/check_systemd
6
6
  Author: Josef Friedrich
@@ -33,7 +33,8 @@ Description: [![pypi.org](http://img.shields.io/pypi/v/check_systemd.svg)](https
33
33
  ## Command line interface
34
34
 
35
35
  ```
36
- usage: check_systemd [-h] [-c SECONDS] [-e UNIT | -u UNIT] [-v] [-V] [-w SECONDS]
36
+ usage: check_systemd [-h] [-u UNIT | -e UNIT] [-n] [-w SECONDS] [-c SECONDS]
37
+ [-t] [-W SECONDS] [-C SECONDS] [-v] [-V]
37
38
 
38
39
  Copyright (c) 2014-18 Andrea Briganti a.k.a 'Kbyte' <kbytesys@gmail.com>
39
40
  Copyright (c) 2019-20 Josef Friedrich <josef@friedrich.rocks>
@@ -42,17 +43,43 @@ Description: [![pypi.org](http://img.shields.io/pypi/v/check_systemd.svg)](https
42
43
 
43
44
  optional arguments:
44
45
  -h, --help show this help message and exit
45
- -c SECONDS, --critical SECONDS
46
- Startup time in seconds to result in critical status.
47
- -e UNIT, --exclude UNIT
48
- Exclude a systemd unit from the checks. This option can be applied multiple times, for example: -e mnt-data.mount -e
49
- task.service. Regular expressions can be used to exclude multiple units at once, for example: -e 'user@\d+\.service'. For
50
- more informations see the Python documentation about regular expressions (https://docs.python.org/3/library/re.html).
51
46
  -u UNIT, --unit UNIT Name of the systemd unit that is being tested.
47
+ -e UNIT, --exclude UNIT
48
+ Exclude a systemd unit from the checks. This option can
49
+ be applied multiple times, for example: -e mnt-
50
+ data.mount -e task.service. Regular expressions can be
51
+ used to exclude multiple units at once, for example: -e
52
+ 'user@\d+\.service'. For more informations see the
53
+ Python documentation about regular expressions
54
+ (https://docs.python.org/3/library/re.html).
55
+ -n, --no-startup-time
56
+ Don’t check the startup time. Using this option the
57
+ options '-w, --warning' and '-c, --critical' have no
58
+ effect. Performance data about the startup time is
59
+ collected, but no critical, warning etc. states are
60
+ triggered.
61
+ -w SECONDS, --warning SECONDS
62
+ Startup time in seconds to result in a warning status.
63
+ Thedefault is 60 seconds.
64
+ -c SECONDS, --critical SECONDS
65
+ Startup time in seconds to result in a critical status.
66
+ Thedefault is 120 seconds.
67
+ -t, --dead-timers Detect dead / inactive timers. See the corresponding
68
+ options '-W, --dead-timer-warning' and '-C, --dead-
69
+ timers-critical'. Dead timers are detected by parsing
70
+ the output of 'systemctl list-timers'. Dead timer rows
71
+ displaying 'n/a' in the NEXT and LEFTcolumns and the
72
+ time span in the column PASSED exceeds the values
73
+ specified with the options '-W, --dead-timer-warning'
74
+ and '-C, --dead-timers-critical'.
75
+ -W SECONDS, --dead-timers-warning SECONDS
76
+ Time ago in seconds for dead / inactive timers to
77
+ trigger a warning state (by default 6 days).
78
+ -C SECONDS, --dead-timers-critical SECONDS
79
+ Time ago in seconds for dead / inactive timers to
80
+ trigger a critical state (by default 7 days).
52
81
  -v, --verbose Increase output verbosity (use up to 3 times).
53
82
  -V, --version show program's version number and exit
54
- -w SECONDS, --warning SECONDS
55
- Startup time in seconds to result in warning status.
56
83
 
57
84
  Performance data:
58
85
  - count_units
@@ -70,6 +97,32 @@ Description: [![pypi.org](http://img.shields.io/pypi/v/check_systemd.svg)](https
70
97
  * https://exchange.icinga.com/joseffriedrich/check_systemd
71
98
  * https://exchange.nagios.org/directory/Plugins/System-Metrics/Processes/check_systemd/details
72
99
 
100
+ ## Behind the scenes
101
+
102
+ To detect failed units this monitoring script runs:
103
+
104
+ ```sh
105
+ systemctl list-units --all --no-legend
106
+ ```
107
+
108
+ To get the startup time it executes:
109
+
110
+ ```sh
111
+ systemd-analyze
112
+ ```
113
+
114
+ To check a specific unit (`-u, --unit`) this command is executed:
115
+
116
+ ```sh
117
+ systemctl is-active <unit-name>
118
+ ```
119
+
120
+ To find dead timers this plugin launches:
121
+
122
+ ```sh
123
+ systemctl list-timers --all
124
+ ```
125
+
73
126
  ## Testing
74
127
 
75
128
  ```
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
2
+
3
3
  """
4
4
  You can redistribute it and/or modify it under the terms of the GNU General
5
5
  Public License as published by the Free Software Foundation, either version 2
@@ -14,10 +14,10 @@ import re
14
14
  import nagiosplugin
15
15
  from nagiosplugin import Metric
16
16
 
17
- __version__ = '2.1.0'
17
+ __version__ = '2.2.0'
18
18
 
19
19
 
20
- class SystemdctlListUnitsResource(nagiosplugin.Resource):
20
+ class SystemctlListUnitsResource(nagiosplugin.Resource):
21
21
  """
22
22
  :param list excludes: A list of systemd unit names.
23
23
  """
@@ -102,17 +102,29 @@ class SystemdctlListUnitsResource(nagiosplugin.Resource):
102
102
  def format_timespan_to_seconds(fmt_timespan):
103
103
  """Convert a timespan format string into secondes.
104
104
 
105
- :param str fmt_timespan: for example `2.345s` or `3min 45.234s`
105
+ https://github.com/systemd/systemd/blob/master/src/basic/time-util.c#L357
106
+
107
+ :param str fmt_timespan: for example `2.345s` or `3min 45.234s` or
108
+ `34min left` or `2 months 8 days`
106
109
 
107
110
  :return: The seconds
108
111
  :rtype: float
109
112
  """
113
+ for replacement in [
114
+ ['years', 'y'],
115
+ ['months', 'month'],
116
+ ['weeks', 'w'],
117
+ ['days', 'd'],
118
+ ]:
119
+ fmt_timespan = fmt_timespan.replace(
120
+ ' ' + replacement[0], replacement[1]
121
+ )
110
122
  seconds = {
111
- 'y': 365 * 24 * 60 * 60,
112
- 'month': 30 * 24 * 60 * 60,
113
- 'w': 7 * 24 * 60 * 60,
114
- 'd': 24 * 60 * 60,
115
- 'h': 60 * 60,
123
+ 'y': 31536000, # 365 * 24 * 60 * 60
124
+ 'month': 2592000, # 30 * 24 * 60 * 60
125
+ 'w': 604800, # 7 * 24 * 60 * 60
126
+ 'd': 86400, # 24 * 60 * 60
127
+ 'h': 3600, # 60 * 60
116
128
  'min': 60,
117
129
  's': 1,
118
130
  'ms': 0.001,
@@ -120,9 +132,10 @@ def format_timespan_to_seconds(fmt_timespan):
120
132
  result = 0
121
133
  for span in fmt_timespan.split():
122
134
  match = re.search(r'([\d\.]+)([a-z]+)', span)
123
- value = match.group(1)
124
- unit = match.group(2)
125
- result += float(value) * seconds[unit]
135
+ if match:
136
+ value = match.group(1)
137
+ unit = match.group(2)
138
+ result += float(value) * seconds[unit]
126
139
  return round(float(result), 3)
127
140
 
128
141
 
@@ -170,6 +183,111 @@ class SystemdAnalyseResource(nagiosplugin.Resource):
170
183
  context='startup_time')
171
184
 
172
185
 
186
+ class SystemctlListTimersResource(nagiosplugin.Resource):
187
+ """There is one type of systemd "degradation" which is normally not
188
+ detected: dead / inactive timers.
189
+ """
190
+
191
+ def __init__(self, excludes=[], *args, **kwargs):
192
+ self.excludes = excludes
193
+ self.warning = kwargs.pop('warning')
194
+ self.critical = kwargs.pop('critical')
195
+ super().__init__(*args, **kwargs)
196
+
197
+ name = 'SYSTEMD'
198
+
199
+ column_names = [
200
+ 'NEXT', 'LEFT', 'LAST', 'PASSED', 'UNIT', 'ACTIVATES'
201
+ ]
202
+
203
+ column_boundaries = None
204
+
205
+ def re_match(self, unit):
206
+ for exclude in self.excludes:
207
+ if re.match(exclude, unit):
208
+ return(True)
209
+ return(False)
210
+
211
+ def detect_column_boundaries(self, heading):
212
+ boundaries = []
213
+ previous_column_start = 0
214
+ for column_title in self.column_names[1:]:
215
+ next_column_start = heading.index(column_title)
216
+ boundaries.append([previous_column_start, next_column_start])
217
+ previous_column_start = next_column_start
218
+ return boundaries
219
+
220
+ def get_column_text(self, row, column_name):
221
+ boundaries = self.column_boundaries[
222
+ self.column_names.index(column_name)
223
+ ]
224
+ return row[boundaries[0]:boundaries[1]].strip()
225
+
226
+ def probe(self):
227
+ """
228
+ :return: generator that emits
229
+ :class:`~nagiosplugin.metric.Metric` objects
230
+ """
231
+ try:
232
+ p = subprocess.Popen(['systemctl', 'list-timers', '--all'],
233
+ stderr=subprocess.PIPE,
234
+ stdin=subprocess.PIPE,
235
+ stdout=subprocess.PIPE)
236
+ stdout, stderr = p.communicate()
237
+ except OSError as e:
238
+ raise nagiosplugin.CheckError(e)
239
+
240
+ if stderr:
241
+ raise nagiosplugin.CheckError(stderr)
242
+
243
+ # NEXT LEFT
244
+ # Sat 2020-05-16 15:11:15 CEST 34min left
245
+
246
+ # LAST PASSED
247
+ # Sat 2020-05-16 14:31:56 CEST 4min 20s ago
248
+
249
+ # UNIT ACTIVATES
250
+ # apt-daily.timer apt-daily.service
251
+ if stdout:
252
+ lines = stdout.decode('utf-8').splitlines()
253
+ table_heading = lines[0]
254
+ self.column_boundaries = self.detect_column_boundaries(
255
+ table_heading
256
+ )
257
+ # Remove the first line because it is the header.
258
+ # Remove the two last lines: empty line + "XX timers listed."
259
+ table_body = lines[1:-2]
260
+
261
+ state = nagiosplugin.Ok # ok
262
+
263
+ for row in table_body:
264
+ unit = self.get_column_text(row, 'UNIT')
265
+ if self.re_match(unit):
266
+ continue
267
+ next_date_time = self.get_column_text(row, 'NEXT')
268
+
269
+ if next_date_time == 'n/a':
270
+ passed_text = self.get_column_text(row, 'PASSED')
271
+
272
+ if passed_text == 'n/a':
273
+ state = nagiosplugin.Critical
274
+ else:
275
+ passed = format_timespan_to_seconds(
276
+ passed_text
277
+ )
278
+
279
+ if passed_text == 'n/a' or passed >= self.critical:
280
+ state = nagiosplugin.Critical
281
+ elif passed >= self.warning:
282
+ state = nagiosplugin.Warn
283
+
284
+ yield Metric(
285
+ name=unit,
286
+ value=state,
287
+ context='dead_timers'
288
+ )
289
+
290
+
173
291
  class SystemctlIsActiveResource(nagiosplugin.Resource):
174
292
 
175
293
  name = 'SYSTEMD'
@@ -218,8 +336,10 @@ class UnitContext(nagiosplugin.Context):
218
336
  (may optionally be consulted)
219
337
  :returns: :class:`~.result.Result`
220
338
  """
221
- hint = '%s: %s' % (metric.name, metric.value) \
222
- if metric.value else metric.name
339
+ if metric.value:
340
+ hint = '{}: {}'.format(metric.name, metric.value)
341
+ else:
342
+ hint = metric.name
223
343
  if metric.value and metric.value != 'active':
224
344
  return self.result_cls(nagiosplugin.Critical, metric=metric,
225
345
  hint=hint)
@@ -227,6 +347,22 @@ class UnitContext(nagiosplugin.Context):
227
347
  return self.result_cls(nagiosplugin.Ok, metric=metric, hint=hint)
228
348
 
229
349
 
350
+ class DeadTimersContext(nagiosplugin.Context):
351
+
352
+ def __init__(self):
353
+ super(DeadTimersContext, self).__init__('dead_timers')
354
+
355
+ def evaluate(self, metric, resource):
356
+ """Determines state of a given metric.
357
+
358
+ :param metric: associated metric that is to be evaluated
359
+ :param resource: resource that produced the associated metric
360
+ (may optionally be consulted)
361
+ :returns: :class:`~.result.Result`
362
+ """
363
+ return self.result_cls(metric.value, metric=metric, hint=metric.name)
364
+
365
+
230
366
  class PerformanceDataContext(nagiosplugin.Context):
231
367
 
232
368
  def __init__(self):
@@ -266,7 +402,7 @@ class SystemdSummary(nagiosplugin.Summary):
266
402
  """
267
403
  summary = []
268
404
  for result in results.most_significant:
269
- if result.context.name in ['startup_time', 'unit']:
405
+ if result.context.name in ['startup_time', 'unit', 'dead_timers']:
270
406
  summary.append(result)
271
407
  return ', '.join(['{0}'.format(result) for result in summary])
272
408
 
@@ -278,14 +414,15 @@ class SystemdSummary(nagiosplugin.Summary):
278
414
  """
279
415
  summary = []
280
416
  for result in results.most_significant:
281
- if result.context.name in ['startup_time', 'unit']:
417
+ if result.context.name in ['startup_time', 'unit', 'dead_timers']:
282
418
  summary.append('{0}: {1}'.format(result.state, result))
283
419
  return summary
284
420
 
285
421
 
286
422
  def get_argparser():
287
423
  parser = argparse.ArgumentParser(
288
- formatter_class=argparse.RawDescriptionHelpFormatter,
424
+ prog='check_systemd', # To get the right command name in the README.
425
+ formatter_class=lambda prog: argparse.RawDescriptionHelpFormatter(prog, width=80), # noqa: E501
289
426
  description= # noqa: E251
290
427
  'Copyright (c) 2014-18 Andrea Briganti a.k.a \'Kbyte\' <kbytesys@gmail.com>\n' # noqa: E501
291
428
  'Copyright (c) 2019-20 Josef Friedrich <josef@friedrich.rocks>\n'
@@ -303,11 +440,11 @@ def get_argparser():
303
440
 
304
441
  exclusive_group = parser.add_mutually_exclusive_group()
305
442
 
306
- parser.add_argument(
307
- '-c', '--critical',
308
- metavar='SECONDS',
309
- default=120,
310
- help='Startup time in seconds to result in critical status.',
443
+ exclusive_group.add_argument(
444
+ '-u', '--unit',
445
+ type=str,
446
+ dest='unit',
447
+ help='Name of the systemd unit that is being tested.',
311
448
  )
312
449
 
313
450
  exclusive_group.add_argument(
@@ -325,11 +462,62 @@ def get_argparser():
325
462
  '(https://docs.python.org/3/library/re.html).',
326
463
  )
327
464
 
328
- exclusive_group.add_argument(
329
- '-u', '--unit',
330
- type=str,
331
- dest='unit',
332
- help='Name of the systemd unit that is being tested.',
465
+ parser.add_argument(
466
+ '-n', '--no-startup-time',
467
+ action='store_true',
468
+ default=False,
469
+ help='Don’t check the startup time. Using this option the options '
470
+ '\'-w, --warning\' and \'-c, --critical\' have no effect. '
471
+ 'Performance data about the startup time is collected, but '
472
+ 'no critical, warning etc. states are triggered.',
473
+ )
474
+
475
+ parser.add_argument(
476
+ '-w', '--warning',
477
+ default=60,
478
+ metavar='SECONDS',
479
+ help='Startup time in seconds to result in a warning status. The'
480
+ 'default is 60 seconds.',
481
+ )
482
+
483
+ parser.add_argument(
484
+ '-c', '--critical',
485
+ metavar='SECONDS',
486
+ default=120,
487
+ help='Startup time in seconds to result in a critical status. The'
488
+ 'default is 120 seconds.',
489
+ )
490
+
491
+ parser.add_argument(
492
+ '-t', '--dead-timers',
493
+ action='store_true',
494
+ help='Detect dead / inactive timers. See the corresponding options '
495
+ '\'-W, --dead-timer-warning\' and '
496
+ '\'-C, --dead-timers-critical\'. '
497
+ 'Dead timers are detected by parsing the output of '
498
+ '\'systemctl list-timers\'. '
499
+ 'Dead timer rows displaying \'n/a\' in the NEXT and LEFT'
500
+ 'columns and the time span in the column PASSED exceeds the '
501
+ 'values specified with the options \'-W, --dead-timer-warning\' '
502
+ 'and \'-C, --dead-timers-critical\'.'
503
+ )
504
+
505
+ parser.add_argument(
506
+ '-W', '--dead-timers-warning',
507
+ metavar='SECONDS',
508
+ type=float,
509
+ default=60 * 60 * 24 * 6,
510
+ help='Time ago in seconds for dead / inactive timers to trigger a '
511
+ 'warning state (by default 6 days).'
512
+ )
513
+
514
+ parser.add_argument(
515
+ '-C', '--dead-timers-critical',
516
+ metavar='SECONDS',
517
+ type=float,
518
+ default=60 * 60 * 24 * 7,
519
+ help='Time ago in seconds for dead / inactive timers to trigger a '
520
+ 'critical state (by default 7 days).'
333
521
  )
334
522
 
335
523
  parser.add_argument(
@@ -345,13 +533,6 @@ def get_argparser():
345
533
  version='%(prog)s {}'.format(__version__),
346
534
  )
347
535
 
348
- parser.add_argument(
349
- '-w', '--warning',
350
- default=60,
351
- metavar='SECONDS',
352
- help='Startup time in seconds to result in warning status.',
353
- )
354
-
355
536
  return parser
356
537
 
357
538
 
@@ -360,30 +541,53 @@ def main():
360
541
 
361
542
  objects = []
362
543
 
544
+ if args.dead_timers:
545
+ objects += [
546
+ SystemctlListTimersResource(
547
+ excludes=args.exclude,
548
+ warning=args.dead_timers_warning,
549
+ critical=args.dead_timers_critical,
550
+ ),
551
+ DeadTimersContext()
552
+ ]
553
+
363
554
  if args.unit:
364
555
  objects.append(SystemctlIsActiveResource(unit=args.unit))
365
556
  else:
366
557
  objects += [
367
- SystemdctlListUnitsResource(excludes=args.exclude),
558
+ SystemctlListUnitsResource(excludes=args.exclude),
368
559
  PerformanceDataContext(),
369
-
370
560
  ]
371
- analyse = subprocess.run(['systemd-analyze'], stderr=subprocess.PIPE,
372
- stdin=subprocess.PIPE, stdout=subprocess.PIPE)
373
- # systemd-analyze: boot not finshed exists with 1
561
+ analyse = subprocess.run(
562
+ ['systemd-analyze'],
563
+ stderr=subprocess.PIPE,
564
+ stdin=subprocess.PIPE,
565
+ stdout=subprocess.PIPE
566
+ )
567
+ # systemd-analyze: boot not finshed exits with 1
374
568
  if analyse.returncode == 0:
375
569
  objects.append(SystemdAnalyseResource())
376
570
 
377
571
  objects += [
378
572
  UnitContext(),
379
- nagiosplugin.ScalarContext(
380
- name='startup_time',
381
- warning=args.warning,
382
- critical=args.critical,
383
- ),
384
573
  SystemdSummary()
385
574
  ]
386
575
 
576
+ if not args.no_startup_time:
577
+ objects.append(
578
+ nagiosplugin.ScalarContext(
579
+ name='startup_time',
580
+ warning=args.warning,
581
+ critical=args.critical,
582
+ )
583
+ )
584
+ else:
585
+ objects.append(
586
+ nagiosplugin.ScalarContext(
587
+ name='startup_time'
588
+ )
589
+ )
590
+
387
591
  check = nagiosplugin.Check(*objects)
388
592
  check.main(args.verbose)
389
593
 
@@ -1,82 +0,0 @@
1
- [![pypi.org](http://img.shields.io/pypi/v/check_systemd.svg)](https://pypi.python.org/pypi/check_systemd)
2
- [![Build Status](https://travis-ci.org/Josef-Friedrich/check_systemd.svg?branch=master)](https://travis-ci.org/Josef-Friedrich/check_systemd)
3
-
4
- # check_systemd
5
-
6
- `check_systemd` is a
7
- [Nagios](https://www.nagios.org) / [Icinga](https://icinga.com)
8
- monitoring plugin to check [systemd](https://systemd.io) for failed
9
- units.
10
-
11
- This Python script will report a degraded system to your monitoring solution.
12
- It requires only the
13
- [nagiosplugin](https://nagiosplugin.readthedocs.io/en/stable) library.
14
-
15
- You can also test a single service with the `-u, --unit` parameter.
16
-
17
- Released under GNU GPLv2 License.
18
-
19
- ## Installation
20
-
21
- ```
22
- pip3 install check_systemd
23
- ```
24
-
25
- ## Command line interface
26
-
27
- ```
28
- usage: check_systemd [-h] [-c SECONDS] [-e UNIT | -u UNIT] [-v] [-V] [-w SECONDS]
29
-
30
- Copyright (c) 2014-18 Andrea Briganti a.k.a 'Kbyte' <kbytesys@gmail.com>
31
- Copyright (c) 2019-20 Josef Friedrich <josef@friedrich.rocks>
32
-
33
- Nagios / Icinga monitoring plugin to check systemd for failed units.
34
-
35
- optional arguments:
36
- -h, --help show this help message and exit
37
- -c SECONDS, --critical SECONDS
38
- Startup time in seconds to result in critical status.
39
- -e UNIT, --exclude UNIT
40
- Exclude a systemd unit from the checks. This option can be applied multiple times, for example: -e mnt-data.mount -e
41
- task.service. Regular expressions can be used to exclude multiple units at once, for example: -e 'user@\d+\.service'. For
42
- more informations see the Python documentation about regular expressions (https://docs.python.org/3/library/re.html).
43
- -u UNIT, --unit UNIT Name of the systemd unit that is being tested.
44
- -v, --verbose Increase output verbosity (use up to 3 times).
45
- -V, --version show program's version number and exit
46
- -w SECONDS, --warning SECONDS
47
- Startup time in seconds to result in warning status.
48
-
49
- Performance data:
50
- - count_units
51
- - startup_time
52
- - units_activating
53
- - units_active
54
- - units_failed
55
- - units_inactive
56
-
57
- ```
58
-
59
- ## Project pages
60
-
61
- * https://github.com/Josef-Friedrich/check_systemd
62
- * https://exchange.icinga.com/joseffriedrich/check_systemd
63
- * https://exchange.nagios.org/directory/Plugins/System-Metrics/Processes/check_systemd/details
64
-
65
- ## Testing
66
-
67
- ```
68
- pyenv install 3.7.6
69
- pyenv install 3.8.1
70
- pyenv local 3.7.6 3.8.1
71
- pip3 install tox
72
- tox
73
- ```
74
-
75
- ## Deploying
76
-
77
- Edit version number in check_systemd.py (without `v`)
78
-
79
- ```
80
- git tag v2.0.11
81
- git push --tags
82
- ```
File without changes
File without changes
File without changes
File without changes