Search code examples
pythonsystemdsystemd-journald

Query python systemd.journal like journalctl -b and journalctl --list-boots for entries related to last boots


I'm looking for a way to query the information provided by journalctl -b and journalctl --list-boots through python systemd module.

I've written a workaround which runs journalctl as a subprocess and parses the output. Maybe there's some more obvious way.

import datetime
import re
import subprocess
from systemd import journal

def parse_datetime_data(data):
    datetimedata_no_tz = data[0:data.rindex(" ")]
    datetimedata_tz = data[data.rindex(" ")+1:-1]

    datetimeValue = datetime.datetime.strptime(datetimedata_no_tz, 
                                               "%a %Y-%m-%d %X")
    return datetimeValue, datetimedata_tz

def get_bootlines():
    bootlinesRaw = subprocess.check_output(['journalctl', '--list-boots', 
                                            '--no-pager'],
                                           encoding="utf-8").splitlines()
    boots = {}

    for bootlineRaw in bootlinesRaw:
        if bootlineRaw:
            lt = re.findall('^ *(-?\d+) (\w+) ([\w -:]+).([\w -:]+)',
                            bootlineRaw)
            linedata = lt[0]

            startdata = linedata[2]
            bootstart,bootstart_tz = parse_datetime_data(startdata)

            enddata = linedata[3]
            bootend,bootend_tz = parse_datetime_data(enddata)

            boots[int(linedata[0])] = {"BOOT_ID":linedata[1],
                                 "start": bootstart, "start_tz": bootstart_tz,
                                 "end": bootstart, "end_tz": bootend_tz}

    return boots

boots = get_bootlines()


Solution

  • By the looks of it, neither systemd.journal or the underlying native module expose an API for listing boots.

    (You can use the _BOOT_ID matcher for the journal reader API once you do have a boot id at hand though.)

    Looking at the source for journalctl, what --list-boots does is it iterates over all known journal entries and keeps the unique boot IDs and their first and last timestamps, so you could do that in your Python code too.

    As an aside, with systemd >= 251 you can just do

    >>> import json
    >>> import subprocess
    >>> json.loads(subprocess.check_output(["journalctl", "--output=json", "--list-boots"]))
    [{'index': 0, 'boot_id': '5ab8a0b2e2624bcdba4d51d83a7a4fe2', 'first_entry': 1658396953303255, 'last_entry': 1662635352510679}]