2012-09-06 18:22:08 -07:00
|
|
|
python-systemd
|
2012-06-25 16:58:29 -07:00
|
|
|
===============
|
|
|
|
|
|
2015-07-05 20:16:46 -04:00
|
|
|
Python module for native access to the systemd facilities. Functionality
|
2016-05-21 08:47:00 +03:00
|
|
|
is separated into a number of modules:
|
2022-08-15 16:02:05 +02:00
|
|
|
- `systemd.journal` supports sending of structured messages to the journal
|
2015-07-05 20:16:46 -04:00
|
|
|
and reading journal files,
|
2022-08-15 16:02:05 +02:00
|
|
|
- `systemd.daemon` wraps parts of `libsystemd` useful for writing daemons
|
2015-07-05 20:16:46 -04:00
|
|
|
and socket activation,
|
2022-08-15 16:02:05 +02:00
|
|
|
- `systemd.id128` provides functions for querying machine and boot identifiers
|
2015-07-05 20:16:46 -04:00
|
|
|
and a lists of message identifiers provided by systemd,
|
2022-08-15 16:02:05 +02:00
|
|
|
- `systemd.login` wraps parts of `libsystemd` used to query logged in users
|
2015-07-05 20:16:46 -04:00
|
|
|
and available seats and machines.
|
2012-06-25 23:02:40 -07:00
|
|
|
|
|
|
|
|
Installation
|
|
|
|
|
============
|
|
|
|
|
|
2015-07-05 20:16:46 -04:00
|
|
|
This module should be packaged for almost all Linux distributions. Use
|
|
|
|
|
|
2022-08-15 16:48:31 +02:00
|
|
|
On Fedora:
|
2015-07-05 20:16:46 -04:00
|
|
|
|
2022-08-15 16:48:31 +02:00
|
|
|
dnf install python3-systemd
|
2015-07-05 20:16:46 -04:00
|
|
|
|
2022-08-15 16:48:31 +02:00
|
|
|
On Debian/Ubuntu/Mint:
|
2015-07-05 20:16:46 -04:00
|
|
|
|
2022-08-15 19:29:28 +02:00
|
|
|
apt update
|
|
|
|
|
apt install python3-systemd
|
2015-07-05 20:16:46 -04:00
|
|
|
|
2022-08-15 16:48:31 +02:00
|
|
|
On openSUSE and SLE:
|
2016-12-17 03:08:42 +01:00
|
|
|
|
2022-08-15 16:48:31 +02:00
|
|
|
zypper in python3-systemd
|
|
|
|
|
|
|
|
|
|
On Arch:
|
|
|
|
|
|
|
|
|
|
pacman -Sy python-systemd
|
2016-12-17 03:08:42 +01:00
|
|
|
|
2023-02-06 19:49:12 +04:00
|
|
|
The project is also available on pypi as `systemd-python`:
|
|
|
|
|
|
2023-02-11 19:00:09 +04:00
|
|
|
[](https://pypi.org/project/systemd-python/)
|
2023-02-06 19:49:12 +04:00
|
|
|
|
2015-07-05 20:16:46 -04:00
|
|
|
To build from source
|
2019-06-16 14:54:14 +02:00
|
|
|
--------------------
|
2015-07-05 20:16:46 -04:00
|
|
|
|
2023-03-26 13:10:45 +02:00
|
|
|
On CentOS, RHEL, and Fedora:
|
2012-09-06 18:22:08 -07:00
|
|
|
|
2015-07-07 12:15:39 -07:00
|
|
|
dnf install git python3-pip gcc python3-devel systemd-devel
|
2022-08-15 16:02:05 +02:00
|
|
|
pip3 install 'git+https://github.com/systemd/python-systemd.git#egg=systemd-python'
|
2012-09-06 18:22:08 -07:00
|
|
|
|
2023-03-26 13:10:45 +02:00
|
|
|
On Debian or Ubuntu:
|
2015-09-04 09:50:51 +02:00
|
|
|
|
2026-04-29 11:27:20 -04:00
|
|
|
apt install libsystemd-dev gcc python3-dev pkg-config
|
2015-09-04 09:50:51 +02:00
|
|
|
|
2012-06-26 01:20:09 -07:00
|
|
|
Usage
|
|
|
|
|
=====
|
|
|
|
|
|
|
|
|
|
Quick example:
|
|
|
|
|
|
2012-09-06 16:48:51 -07:00
|
|
|
from systemd import journal
|
|
|
|
|
journal.send('Hello world')
|
|
|
|
|
journal.send('Hello, again, world', FIELD2='Greetings!', FIELD3='Guten tag')
|
|
|
|
|
journal.send('Binary message', BINARY=b'\xde\xad\xbe\xef')
|
2012-06-28 13:32:03 -04:00
|
|
|
|
2022-08-15 16:02:05 +02:00
|
|
|
There is one required argument — the message, and additional fields
|
2012-06-28 13:32:03 -04:00
|
|
|
can be specified as keyword arguments. Following the journald API, all
|
|
|
|
|
names are uppercase.
|
|
|
|
|
|
|
|
|
|
The journald sendv call can also be accessed directly:
|
|
|
|
|
|
2012-09-06 16:48:51 -07:00
|
|
|
from systemd import journal
|
|
|
|
|
journal.sendv('MESSAGE=Hello world')
|
|
|
|
|
journal.sendv('MESSAGE=Hello, again, world', 'FIELD2=Greetings!',
|
2012-06-28 13:32:03 -04:00
|
|
|
'FIELD3=Guten tag')
|
2012-09-06 16:48:51 -07:00
|
|
|
journal.sendv('MESSAGE=Binary message', b'BINARY=\xde\xad\xbe\xef')
|
2012-06-28 13:32:03 -04:00
|
|
|
|
|
|
|
|
The two examples should give the same results in the log.
|
2012-06-26 01:20:09 -07:00
|
|
|
|
2021-01-02 23:05:35 +00:00
|
|
|
Reading from the journal is often similar to using the `journalctl` utility.
|
|
|
|
|
|
|
|
|
|
Show all entries since 20 minutes ago (`journalctl --since "20 minutes ago"`):
|
|
|
|
|
|
|
|
|
|
from systemd import journal
|
|
|
|
|
from datetime import datetime, timedelta
|
|
|
|
|
j = journal.Reader()
|
|
|
|
|
j.seek_realtime(datetime.now() - timedelta(minutes=20))
|
|
|
|
|
for entry in j:
|
|
|
|
|
print(entry['MESSAGE'])
|
|
|
|
|
|
|
|
|
|
Show entries between two timestamps (`journalctl --since "50 minutes ago" --until "10 minutes ago"`):
|
|
|
|
|
|
|
|
|
|
from systemd import journal
|
|
|
|
|
from datetime import datetime, timedelta
|
|
|
|
|
j = journal.Reader()
|
|
|
|
|
since = datetime.now() - timedelta(minutes=50)
|
|
|
|
|
until = datetime.now() - timedelta(minutes=10)
|
|
|
|
|
j.seek_realtime(since)
|
|
|
|
|
for entry in j:
|
|
|
|
|
if entry['__REALTIME_TIMESTAMP'] > until:
|
|
|
|
|
break
|
|
|
|
|
print(entry['MESSAGE'])
|
|
|
|
|
|
|
|
|
|
Show explanations of log messages alongside entries (`journalctl -x`):
|
|
|
|
|
|
|
|
|
|
from systemd import journal
|
|
|
|
|
j = journal.Reader()
|
|
|
|
|
for entry in j:
|
|
|
|
|
print("MESSAGE: ", entry['MESSAGE'])
|
|
|
|
|
try:
|
|
|
|
|
print("CATALOG: ", j.get_catalog())
|
|
|
|
|
except:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
Show entries by a specific executable (`journalctl /usr/bin/vim`):
|
|
|
|
|
|
|
|
|
|
from systemd import journal
|
|
|
|
|
j = journal.Reader()
|
|
|
|
|
j.add_match('_EXE=/usr/bin/vim')
|
|
|
|
|
for entry in j:
|
|
|
|
|
print(entry['MESSAGE'])
|
|
|
|
|
|
2022-08-15 16:02:05 +02:00
|
|
|
- Note: matches can be added from many different fields, for example
|
|
|
|
|
entries from a specific process ID can be matched with the `_PID`
|
|
|
|
|
field, and entries from a specific unit (ie. `journalctl -u
|
|
|
|
|
systemd-udevd.service`) can be matched with `_SYSTEMD_UNIT`.
|
|
|
|
|
See all fields available at the
|
|
|
|
|
[systemd.journal-fields docs](https://www.freedesktop.org/software/systemd/man/systemd.journal-fields.html).
|
2021-01-02 23:12:15 +00:00
|
|
|
|
2021-01-02 23:07:49 +00:00
|
|
|
Show kernel ring buffer (`journalctl -k`):
|
2021-01-02 23:05:35 +00:00
|
|
|
|
|
|
|
|
from systemd import journal
|
|
|
|
|
j = journal.Reader()
|
|
|
|
|
j.add_match('_TRANSPORT=kernel')
|
|
|
|
|
for entry in j:
|
|
|
|
|
print(entry['MESSAGE'])
|
|
|
|
|
|
|
|
|
|
Read entries in reverse (`journalctl _EXE=/usr/bin/vim -r`):
|
|
|
|
|
|
|
|
|
|
from systemd import journal
|
|
|
|
|
class ReverseReader(journal.Reader):
|
|
|
|
|
def __next__(self):
|
|
|
|
|
ans = self.get_previous()
|
|
|
|
|
if ans:
|
|
|
|
|
return ans
|
|
|
|
|
raise StopIteration()
|
|
|
|
|
|
|
|
|
|
j = ReverseReader()
|
|
|
|
|
j.add_match('_EXE=/usr/bin/vim')
|
|
|
|
|
j.seek_tail()
|
|
|
|
|
for entry in j:
|
|
|
|
|
print(entry['MESSAGE'])
|
|
|
|
|
|
|
|
|
|
|
2019-06-16 14:54:14 +02:00
|
|
|
Notes
|
|
|
|
|
-----
|
2012-06-26 01:20:09 -07:00
|
|
|
|
2022-08-15 16:02:05 +02:00
|
|
|
* Unlike the native C version of journald's `sd_journal_send()`,
|
2022-08-16 10:45:30 +02:00
|
|
|
printf-style substitution is not supported. Perform any substitution
|
|
|
|
|
using Python's f-strings first (or `.format()` or the `%` operator).
|
2022-08-15 16:02:05 +02:00
|
|
|
* A `ValueError` is raised if `sd_journald_sendv()` results in an
|
2022-08-16 10:45:30 +02:00
|
|
|
error. This might happen if there are no arguments or one of them is
|
|
|
|
|
invalid.
|
2012-06-26 01:20:09 -07:00
|
|
|
|
2018-05-23 12:30:21 -07:00
|
|
|
A handler class for the Python logging framework is also provided:
|
|
|
|
|
|
|
|
|
|
import logging
|
|
|
|
|
from systemd import journal
|
|
|
|
|
logger = logging.getLogger('custom_logger_name')
|
2021-03-19 13:15:29 +01:00
|
|
|
logger.addHandler(journal.JournalHandler(SYSLOG_IDENTIFIER='custom_unit_name'))
|
2018-05-23 12:30:21 -07:00
|
|
|
logger.warning("Some message: %s", 'detail')
|
|
|
|
|
|
2022-08-15 16:02:05 +02:00
|
|
|
`libsystemd` version compatibility
|
|
|
|
|
----------------------------------
|
2019-06-16 18:19:15 +02:00
|
|
|
|
2022-08-15 16:02:05 +02:00
|
|
|
This module may be compiled against any version of `libsystemd`. At
|
2019-06-16 18:19:15 +02:00
|
|
|
compilation time, any functionality that is not available in that
|
2022-08-15 16:02:05 +02:00
|
|
|
version is disabled, and the resulting binary module will depend on
|
|
|
|
|
symbols that were available at compilation time. This means that the
|
|
|
|
|
resulting binary module is compatible with that or any later version
|
|
|
|
|
of `libsystemd`. To obtain maximum possible functionality, this module
|
|
|
|
|
must be compile against suitably recent libsystemd.
|
2019-06-16 18:19:15 +02:00
|
|
|
|
2016-09-15 22:29:25 +02:00
|
|
|
Documentation
|
|
|
|
|
=============
|
|
|
|
|
|
|
|
|
|
Online documentation can be found at [freedesktop.org](https://www.freedesktop.org/software/systemd/python-systemd/)
|
|
|
|
|
|
|
|
|
|
To build it locally run:
|
|
|
|
|
|
2025-10-03 21:08:09 +02:00
|
|
|
ninja -C build html
|
2016-09-15 22:29:25 +02:00
|
|
|
|
2025-10-03 21:08:09 +02:00
|
|
|
Or use any other builder, see `man sphinx-build` for a list. The compiled docs will be e.g. in `build/html`.
|
2016-09-15 22:29:25 +02:00
|
|
|
|
2012-06-26 01:20:09 -07:00
|
|
|
Viewing Output
|
|
|
|
|
==============
|
|
|
|
|
|
|
|
|
|
Quick way to view output with all fields as it comes in:
|
|
|
|
|
|
|
|
|
|
sudo journalctl -f --output=json
|
|
|
|
|
|
|
|
|
|
Test Builds (for Development)
|
|
|
|
|
=============================
|
2012-06-25 23:07:03 -07:00
|
|
|
|
2025-06-30 12:07:47 +07:00
|
|
|
python -m build
|
|
|
|
|
python -m pip install .
|
2012-06-25 23:07:03 -07:00
|
|
|
python
|
2012-09-06 16:48:51 -07:00
|
|
|
>>> from systemd import journal
|
|
|
|
|
>>> journal.send("Test")
|
2015-09-03 20:27:36 +02:00
|
|
|
|
|
|
|
|
[](https://semaphoreci.com/zbyszek/python-systemd)
|