我试图使用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'])
这里有一些问题
理想情况下,我希望根据一组过滤器/匹配来跟踪此日记,以模拟命令' 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'])
答案 0 :(得分:8)
我也在研究类似的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负载,因为读取器的状态仍然是“可读的”#34;甚至在获得一个条目之后,这导致了太多的poll()。
根据以下链接,似乎我们必须在每次poll()之后调用 sd_journal_process (在python systemd模块中,即journal.Reader()。process()),以便重置文件描述符的可读状态。
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'])
修改强>: 删除" j.get_next()"在j.get_previous()之后。
答案 1 :(得分:2)
上一个答案有效,并且在seek_tail()之后调用get_next()的提示确实很重要。
一种更简单的方法(但显然使用轮询的先前版本在更大的应用程序中更灵活)
import systemd.journal
def main():
j = systemd.journal.Reader()
j.seek_tail()
j.get_previous()
while True:
event = j.wait(-1)
if event == systemd.journal.APPEND:
for entry in j:
print entry['MESSAGE']
if __name__ == '__main__':
main()
如果想要详细观察发生了什么,支持调试输出的以下版本可能会有所帮助(用一些参数调用它会打开它)
import sys
import systemd.journal
def main(debug):
j = systemd.journal.Reader()
j.seek_tail()
j.get_previous()
while True:
event = j.wait(-1)
if event == systemd.journal.APPEND:
for entry in j:
print entry['MESSAGE']
elif debug and event == systemd.journal.NOP:
print "DEBUG: NOP"
elif debug and event == systemd.journal.INVALIDATE:
print "DEBUG: INVALIDATE"
elif debug:
raise ValueError, event
if __name__ == '__main__':
main(len(sys.argv) > 1)
对我而言,它始终在一个INVALIDATE开头。不确定这是什么意思。有一些用作迭代器失效的东西听起来我可能会以某种方式重新创建/重新打开/刷新它。但至少在我的基本测试中,上面的代码才起作用。不确定是否有任何竞争条件。实际上我很难解释代码是如何没有种族的。