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.
- {check_systemd-2.1.0 → check_systemd-2.2.0}/PKG-INFO +63 -10
- check_systemd-2.2.0/README.md +135 -0
- {check_systemd-2.1.0 → check_systemd-2.2.0}/check_systemd.egg-info/PKG-INFO +63 -10
- {check_systemd-2.1.0 → check_systemd-2.2.0}/check_systemd.py +248 -44
- check_systemd-2.1.0/README.md +0 -82
- {check_systemd-2.1.0 → check_systemd-2.2.0}/LICENSE +0 -0
- {check_systemd-2.1.0 → check_systemd-2.2.0}/MANIFEST.in +0 -0
- {check_systemd-2.1.0 → check_systemd-2.2.0}/check_systemd.egg-info/SOURCES.txt +0 -0
- {check_systemd-2.1.0 → check_systemd-2.2.0}/check_systemd.egg-info/dependency_links.txt +0 -0
- {check_systemd-2.1.0 → check_systemd-2.2.0}/check_systemd.egg-info/entry_points.txt +0 -0
- {check_systemd-2.1.0 → check_systemd-2.2.0}/check_systemd.egg-info/requires.txt +0 -0
- {check_systemd-2.1.0 → check_systemd-2.2.0}/check_systemd.egg-info/top_level.txt +0 -0
- {check_systemd-2.1.0 → check_systemd-2.2.0}/setup.cfg +0 -0
- {check_systemd-2.1.0 → check_systemd-2.2.0}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: check_systemd
|
|
3
|
-
Version: 2.
|
|
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: [](https
|
|
|
33
33
|
## Command line interface
|
|
34
34
|
|
|
35
35
|
```
|
|
36
|
-
usage: check_systemd [-h] [-
|
|
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: [](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: [](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
|
+
[](https://pypi.python.org/pypi/check_systemd)
|
|
2
|
+
[](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.
|
|
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: [](https
|
|
|
33
33
|
## Command line interface
|
|
34
34
|
|
|
35
35
|
```
|
|
36
|
-
usage: check_systemd [-h] [-
|
|
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: [](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: [](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
|
-
|
|
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.
|
|
17
|
+
__version__ = '2.2.0'
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
class
|
|
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
|
-
|
|
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
|
-
|
|
124
|
-
|
|
125
|
-
|
|
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
|
-
|
|
222
|
-
|
|
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
|
-
|
|
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
|
-
|
|
307
|
-
'-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
help='
|
|
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
|
-
|
|
329
|
-
'-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
help='
|
|
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
|
-
|
|
558
|
+
SystemctlListUnitsResource(excludes=args.exclude),
|
|
368
559
|
PerformanceDataContext(),
|
|
369
|
-
|
|
370
560
|
]
|
|
371
|
-
analyse = subprocess.run(
|
|
372
|
-
|
|
373
|
-
|
|
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
|
|
check_systemd-2.1.0/README.md
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
[](https://pypi.python.org/pypi/check_systemd)
|
|
2
|
-
[](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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|