python - 从 Python 脚本中读取 systemd 日志

标签 python systemd journal

我正在尝试使用 systemd 库在 Python 中模拟这个 shell 命令 http://www.freedesktop.org/software/systemd/python-systemd/journal.html

我实际上是在尝试在 Python 中模拟此命令。

journalctl --since=-5m --no-pager

我看到其他人通过调用日志可执行文件在 Python 中执行此操作,但这是一种非常糟糕的执行方式。

我根据上面链接的文档编写了这个简单的脚本

import select
from systemd import journal

j = journal.Reader()
j.log_level(journal.LOG_INFO)
# j.add_match(_SYSTEMD_UNIT="systemd-udevd.service")

j.seek_tail()
j.get_next()

while j.get_next():
    for entry in j:
        if entry['MESSAGE'] != "":
            print(str(entry['__REALTIME_TIMESTAMP'] )+ ' ' + entry['MESSAGE'])

这里有几个问题

  1. 日志似乎是从大约 5 天前开始的,这意味着 seek_tail 似乎没有工作。
  2. 我在这里得到了很多垃圾,我应该使用一个特定的过滤器来匹配我从问题开头给出的 journalctl 命令获得的数据吗?

理想情况下,我只想根据一组过滤器/匹配项来关注该期刊,以模拟“journalctl -f”命令,但我只需要先解决这个问题。我想以这样的方式结束,但它也不起作用。

import select
from systemd import journal

j = journal.Reader()
j.log_level(journal.LOG_INFO)

# j.add_match(_SYSTEMD_UNIT="systemd-udevd.service")
j.seek_tail()

p = select.poll()
p.register(j, j.get_events())
while p.poll():

    while j.get_next():
        for entry in j:
            if entry['MESSAGE'] != "":
                print(str(entry['__REALTIME_TIMESTAMP'] )+ ' ' + entry['MESSAGE'])

最佳答案

我也在研究类似的 python 模块。

根据以下链接,我们必须调用sd_journal_previous(在python systemd模块中,即journal.Reader().get_previous())。

http://www.freedesktop.org/software/systemd/man/sd_journal_seek_tail.html

https://bugs.freedesktop.org/show_bug.cgi?id=64614

此外,您的示例代码将消耗 80 - 100% 的 CPU 负载,因为读取器的状态即使在获得条目后仍保持“可读”状态,这会导致过多的 poll()

根据以下链接,似乎我们必须在每次调用之后调用sd_journal_process(在python systemd模块中,即journal.Reader().process()) poll(),为了重置文件描述符的可读状态。

http://www.freedesktop.org/software/systemd/man/sd_journal_get_events.html

总之,您的示例代码将是:

import select
from systemd import journal

j = journal.Reader()
j.log_level(journal.LOG_INFO)

# j.add_match(_SYSTEMD_UNIT="systemd-udevd.service")
j.seek_tail()
j.get_previous()
# j.get_next() # it seems this is not necessary.

p = select.poll()
p.register(j, j.get_events())

while p.poll():
    if j.process() != journal.APPEND:
        continue

    # Your example code has too many get_next() (i.e, "while j.get_next()" and "for event in j") which cause skipping entry.
    # Since each iteration of a journal.Reader() object is equal to "get_next()", just do simple iteration.
    for entry in j:
        if entry['MESSAGE'] != "":
            print(str(entry['__REALTIME_TIMESTAMP'] )+ ' ' + entry['MESSAGE'])

关于python - 从 Python 脚本中读取 systemd 日志,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26331116/

相关文章:

ubuntu - 尝试使用 systemd 在 ubuntu 服务器上运行 apache Airflow

logging - 使用不带日志的 systemd

python - 在实例方法中从父级访问类属性

python - 无法阻止标签扩展主窗口

timer - systemd 计时器 AccuracySec 参数使滴答声滑动是否正确?

systemd - 如何运行多个命令 systemd

sqlite - 使用 -journal 文件在只读文件系统上打开 sqlite3 DB

python - 使用字典将 python 数据类型转换为其他语言的数据类型

python - 如何应用 sklearn 的 EllipticEnvelope 找出给定数据集中的最高异常值?