Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/mosquito/cysystemd
systemd wrapper on Cython
https://github.com/mosquito/cysystemd
cython journald python python-2 python-3 python-3-5 python-3-6 systemd wrapper
Last synced: 4 days ago
JSON representation
systemd wrapper on Cython
- Host: GitHub
- URL: https://github.com/mosquito/cysystemd
- Owner: mosquito
- License: apache-2.0
- Created: 2016-08-29T18:26:43.000Z (about 8 years ago)
- Default Branch: master
- Last Pushed: 2024-05-29T10:09:20.000Z (4 months ago)
- Last Synced: 2024-05-29T20:39:11.974Z (4 months ago)
- Topics: cython, journald, python, python-2, python-3, python-3-5, python-3-6, systemd, wrapper
- Language: Cython
- Homepage:
- Size: 146 KB
- Stars: 99
- Watchers: 5
- Forks: 22
- Open Issues: 6
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
![pypi version](https://img.shields.io/pypi/v/cysystemd.svg) ![](https://img.shields.io/pypi/pyversions/cysystemd.svg) ![License](https://img.shields.io/pypi/l/cysystemd.svg)
# systemd wrapper in Cython
Python systemd wrapper using Cython.
## Installation
All packages available on `github releases `_.
### Installation from binary wheels
* wheels is now available for Python 3.8, 3.9, 3.10, 3.11, 3.12
for `x86_64` and `arm64````shell
python3.10 -m pip install \
https://github.com/mosquito/cysystemd/releases/download/1.6.2/cysystemd-1.6.2-cp310-cp310-linux_x86_64.whl
```### Installation from sources
You **must** install **systemd headers**
For Debian/Ubuntu users:
```shell
apt install build-essential libsystemd-dev
```On older versions of Debian/Ubuntu, you might also need to install:
```shell
apt install libsystemd-daemon-dev libsystemd-journal-dev
```For CentOS/RHEL
```shell
yum install gcc systemd-devel
```And install it from pypi
```shell
pip install cysystemd
```## Usage examples
### Writing to journald
#### Logging handler for python logger
```python
from cysystemd import journal
import logging
import uuidlogging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger()
logger.addHandler(journal.JournaldLogHandler())try:
logger.info("Trying to do something")
raise Exception('foo')
except:
logger.exception("Test Exception %s", 1)
```#### systemd daemon notification
```python
from cysystemd.daemon import notify, Notification# Send READY=1
notify(Notification.READY)# Send status
notify(Notification.STATUS, "I'm fine.")# Send stopping
notify(Notification.STOPPING)
```Write message into systemd journal:
```python
from cysystemd import journaljournal.write("Hello Lennart")
# Or send structured data
journal.send(
message="Hello Lennart",
priority=journal.Priority.INFO,
some_field='some value',
)
```### Reading journald
#### Reading all systemd records
```python
from cysystemd.reader import JournalReader, JournalOpenMode
journal_reader = JournalReader()
journal_reader.open(JournalOpenMode.SYSTEM)
journal_reader.seek_head()for record in journal_reader:
print(record.data['MESSAGE'])
```#### Read only cron logs
```python
from cysystemd.reader import JournalReader, JournalOpenMode, Rulerules = (
Rule("SYSLOG_IDENTIFIER", "CRON") &
Rule("_SYSTEMD_UNIT", "crond.service") |
Rule("_SYSTEMD_UNIT", "cron.service")
)cron_reader = JournalReader()
cron_reader.open(JournalOpenMode.SYSTEM)
cron_reader.seek_head()
cron_reader.add_filter(rules)for record in cron_reader:
print(record.data['MESSAGE'])
```#### Polling records
```python
from cysystemd.reader import JournalReader, JournalOpenModereader = JournalReader()
reader.open(JournalOpenMode.SYSTEM)
reader.seek_tail()poll_timeout = 255
while True:
reader.wait(poll_timeout)for record in reader:
print(record.data['MESSAGE'])
```#### journald open modes
* `CURRENT_USER`
* `LOCAL_ONLY`
* `RUNTIME_ONLY`
* `SYSTEM`
* `SYSTEM_ONLY` - deprecated alias of `SYSTEM````python
from cysystemd.reader import JournalReader, JournalOpenModereader = JournalReader()
reader.open(JournalOpenMode.CURRENT_USER)
```#### journald entry
JournalEntry class has some special properties and methods:
* `data` - journal entry content (`dict`)
* `date` - entry timestamp (`datetime` instance)
* `cursor` - systemd identification bytes for this entry
* `boot_id()` - returns bootid
* `get_realtime_sec()` - entry epoch (`float`)
* `get_realtime_usec()` - entry epoch (`int` microseconds)
* `get_monotonic_sec()` - entry monotonic time (`float`)
* `get_monotonic_usec()` - entry monotonic time (`int` microseconds)
* `__getitem__(key)` - shoutcut for `entry.data[key]`#### journald reader
JournalReader class has some special properties and methods:
* `open(flags=JournalOpenMode.CURRENT_USER)` - opening journald
with selected mode
* `open_directory(path)` - opening journald from path
* `open_files(*filename)` - opening journald from files
* `data_threshold` - may be used to get or set the data field size threshold
for data returned by fething entry data.
* `closed` - returns True when journal reader closed
* `locked` - returns True when journal reader locked
* `idle` - returns True when journal reader opened
* `seek_head` - move reader pointer to the first entry
* `seek_tail` - move reader pointer to the last entry
* `seek_monotonic_usec` - seeks to the entry with the specified monotonic
timestamp, i.e. CLOCK_MONOTONIC. Since monotonic time restarts on every
reboot a boot ID needs to be specified as well.
* `seek_realtime_usec` - seeks to the entry with the specified realtime
(wallclock) timestamp, i.e. CLOCK_REALTIME. Note that the realtime clock
is not necessarily monotonic. If a realtime timestamp is ambiguous, it is
not defined which position is sought to.
* `seek_cursor` - seeks to the entry located at the specified cursor
(see `JournalEntry.cursor`).
* `wait(timeout)` - It will synchronously wait until the journal gets
changed. The maximum time this call sleeps may be controlled with the
timeout_usec parameter.
* `__iter__` - returns JournalReader object
* `__next__` - calls `next()` or raise `StopIteration`
* `next(skip=0)` - returns the next `JournalEntry`. The `skip`
parameter skips some entries.
* `previous(skip=0)` - returns the previous `JournalEntry`.
The `skip` parameter skips some entries.
* `skip_next(skip)` - skips next entries.
* `skip_previous(skip)` - skips next entries.
* `add_filter(rule)` - adding filter rule.
See `read-only-cron-logs`_ as example.
* `clear_filter` - reset all filters
* `fd` - returns a special file descriptor
* `events` - returns `EPOLL` events
* `timeout` - returns internal timeout
* `process_events()` - After each poll() wake-up process_events() needs
to be called to process events. This call will also indicate what kind of
change has been detected.
* `get_catalog()` - retrieves a message catalog entry for the current
journal entry. This will look up an entry in the message catalog by using
the "MESSAGE_ID=" field of the current journal entry. Before returning
the entry all journal field names in the catalog entry text enclosed in
"@" will be replaced by the respective field values of the current entry.
If a field name referenced in the message catalog entry does not exist,
in the current journal entry, the "@" will be removed, but the field name
otherwise left untouched.
* `get_catalog_for_message_id(message_id: UUID)` - works similar to
`get_catalog()` but the entry is looked up by the specified
message ID (no open journal context is necessary for this),
and no field substitution is performed.### Asyncio support
Initial `asyncio` support for reading journal asynchronously.
#### AsyncJournalReader
Blocking methods were wrapped by threads.
Method `wait()` use epoll on journald file descriptor.```python
import asyncio
import jsonfrom cysystemd.reader import JournalOpenMode
from cysystemd.async_reader import AsyncJournalReaderasync def main():
reader = AsyncJournalReader()
await reader.open(JournalOpenMode.SYSTEM)
await reader.seek_tail()while await reader.wait():
async for record in reader:
print(
json.dumps(
record.data,
indent=1,
sort_keys=True
)
)if __name__ == '__main__':
asyncio.run(main())
```