- Repository
- Munin (contrib)
- Last change
- 2020-12-05
- Graph Categories
- Family
- auto
- Capabilities
- Keywords
- Language
- Python (3.x)
- License
- GPL-2.0-only
- Authors
systemd_status
Name
systemd_status - monitor systemd service status, including normal services, mounts, hotplugs and socket activations
Applicable Systems
Linux systems with systemd installed.
Configuration
No configuration is required for this plugin.
Warning level for systemd “failed” state is set to 0:0. If any of the services enters “failed” state, Munin will emit warning.
Author
Kim B. Heino b@bbbs.net
License
GPLv2
Magic Markers
#%# family=auto
#%# capabilities=autoconf
#!/usr/bin/env python3
# pylint: disable=invalid-name
# pylint: enable=invalid-name
"""Munin plugin to monitor systemd service status.
=head1 NAME
systemd_status - monitor systemd service status, including normal services,
mounts, hotplugs and socket activations
=head1 APPLICABLE SYSTEMS
Linux systems with systemd installed.
=head1 CONFIGURATION
No configuration is required for this plugin.
Warning level for systemd "failed" state is set to 0:0. If any of the services
enters "failed" state, Munin will emit warning.
=head1 AUTHOR
Kim B. Heino <b@bbbs.net>
=head1 LICENSE
GPLv2
=head1 MAGIC MARKERS
#%# family=auto
#%# capabilities=autoconf
=cut
"""
import os
import re
import subprocess
import sys
STATES = (
'failed',
'dead',
'running',
'exited',
'active',
'listening',
'waiting',
'plugged',
'mounted',
)
def config():
"""Autoconfig values."""
print('graph_title systemd services')
print('graph_vlabel Services')
print('graph_category processes')
print('graph_args --base 1000 --lower-limit 0')
print('graph_scale no')
print('graph_info Number of services in given activation state.')
for state in STATES:
print('{state}.label Services in {state} state'.format(state=state))
print('failed.warning 0:0')
if os.environ.get('MUNIN_CAP_DIRTYCONFIG') == '1':
fetch()
def fetch():
"""Print runtime values."""
# Get data
try:
# deb9/py3.5 doesn't have encoding parameter in subprocess
output = subprocess.check_output(['/bin/systemctl', 'list-units'])
except (OSError, subprocess.CalledProcessError):
return
output = output.decode('utf-8', 'ignore')
# Parse data
states = {state: 0 for state in STATES}
for line in output.splitlines():
token = line.split()
if len(token) < 4:
continue
if len(token[0]) < 3: # Skip failed-bullet
token = token[1:]
if token[0].endswith('.scope'):
continue # Ignore scopes
if re.match(r'user.*@\d+\.service', token[0]):
continue # These fail randomly in older systemd
if token[3] in states:
states[token[3]] = states[token[3]] + 1
# Output
for state in STATES:
print('{}.value {}'.format(state, states[state]))
if __name__ == '__main__':
if len(sys.argv) > 1 and sys.argv[1] == 'autoconf':
print('yes' if os.path.exists('/run/systemd/system') else
'no (systemd is not running)')
elif len(sys.argv) > 1 and sys.argv[1] == 'config':
config()
else:
fetch()