mosquito / cysystemd

systemd wrapper on Cython
Apache License 2.0
101 stars 22 forks source link
cython journald python python-2 python-3 python-3-5 python-3-6 systemd wrapper

pypi version License

systemd wrapper in Cython

Python systemd wrapper using Cython.

Installation

All packages available on github releases <https://github.com/mosquito/cysystemd/releases>_.

Installation from binary wheels

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:

apt install build-essential libsystemd-dev

On older versions of Debian/Ubuntu, you might also need to install:

apt install libsystemd-daemon-dev libsystemd-journal-dev

For CentOS/RHEL

yum install gcc systemd-devel

And install it from pypi

pip install cysystemd

Usage examples

Writing to journald

Logging handler for python logger

from cysystemd import journal
import logging
import uuid

logging.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

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:

from cysystemd import journal

journal.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


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

from cysystemd.reader import JournalReader, JournalOpenMode, Rule

rules = (
  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

from cysystemd.reader import JournalReader, JournalOpenMode

reader = 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

from cysystemd.reader import JournalReader, JournalOpenMode

reader = JournalReader()
reader.open(JournalOpenMode.CURRENT_USER)

journald entry

JournalEntry class has some special properties and methods:

journald reader

JournalReader class has some special properties and methods:

Asyncio support

Initial asyncio support for reading journal asynchronously.

AsyncJournalReader

Blocking methods were wrapped by threads. Method wait() use epoll on journald file descriptor.

import asyncio
import json

from cysystemd.reader import JournalOpenMode
from cysystemd.async_reader import AsyncJournalReader

async 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())