Анализ выходных сообщений монитора dbus - PullRequest
1 голос
/ 23 апреля 2019

Я пытаюсь разобрать выходные сообщения монитора dbus. Он содержит большинство сообщений в виде многострочных записей (включая параметры). Мне нужно проанализировать и объединить отдельные сообщения журнала в одну строку.

Вывод dbus-monitor выводится, как показано ниже,

method call time=462.117843 sender=:1.62 -> destination=org.freedesktop.filehandler serial=122 path=/org/freedesktop/filehandler/routing; interface=org.freedesktop.filehandler.routing; member=start
int16 29877
uint16 0
method return time=462.117844 sender=org.freedesktop.filehandler -> destination=:1.62 serial=2210 reply_serial=122
int16 29877
uint16 0
method call time=462.117845 sender=:1.62 -> destination=org.freedesktop.filehandler serial=123 path=/org/freedesktop/filehandler/routing; interface=org.freedesktop.filehandler.routing; member=comment
string "starting .."
string "routing"
method return time=462.117846 sender=:1.19 -> destination=:1.62 serial=2212 reply_serial=123
int12 -23145
signal time=463.11223 sender=:1.64 -> destination=(null destination) serial=124 path=/org/freedesktop/fileserver; interface=org.freedesktop.DBus.Properties; member=PropertiesChanged
  string "com.freedesktop.Systemserver"
  array[
    dict entry(
      string "SystemTime"
      variant       struct{
            byte 12
            byte 9
            byte 0
        }
    )
  ]
  array [
  ]

Это регулярное выражение Я пытался сгруппировать сообщения dbus (параметр не сгруппирован),

\b(signal|method call|method return)\b time=([\d,.]*) sender=([\w,.,:,(,), ]*) -> destination=([\w,.,:,(,), ]*) serial=([(,),\w]*) (?:path=([\w,\/]*); interface=([\w,.]*); member=([\w,_,-]*))?(?:reply_serial=([\d]*))?

Я ожидаю вывод в следующем формате,

C [sender,serial] path interface+member (parameter1, parameter2, ...)
R [destination,reply_serial] interface+member (parameter1, parameter2, ...)
S [sender, serial] path interface+member (parameter1, parameter2, ...)

Пример вывода для приведенных выше сообщений dbus-monitor показан ниже,

C [:1.62,122] /org/freedesktop/filehandler/routing org.freedesktop.filehandler.routing.start (29877,0)
R [:1.62,122] org.freedesktop.filehandler.routing.start (29877,0)
C [:1.62,123] /org/freedesktop/filehandler/routing org.freedesktop.filehandler.routing.comment ("starting", "routing")
R [:1.62,123] org.freedesktop.filehandler.routing.comment (-23145)
S [:1.64, 124] /org/freedesktop/fileserver org.freedesktop.DBus.Properties.PropertiesChanged ("com.freedesktop.Systemserver"[("SystemTime",{12,9,0})][])

Как достичь ожидаемого результата, если записи обычно состоят из нескольких строк? Кроме того, СИГНАЛЫ имеют несколько инкапсуляций, что затрудняет доступ к параметрам. Может ли кто-нибудь помочь с анализом этих сообщений dbus в ожидаемом формате?

Ответы [ 3 ]

0 голосов
/ 24 апреля 2019

Поскольку у вас уже есть пригодное для использования регулярное выражение, вы можете использовать его с re.split для получения необходимых частей сообщения. Обратите внимание, что это дает отдельную строку для каждой группы захвата плюс одну строку с параметрами для каждой записи сообщения. В этом примере предполагается, что все сообщения находятся в строке messages:

import re
import sys
regex = r'\b(signal|method call|method return)\b time=([\d,.]*) sender=([\w,.,:,(,), ]*) -> destination=([\w,.,:,(,), ]*) serial=([(,),\w]*) (?:path=([\w,\/]*); interface=([\w,.]*); member=([\w,_,-]*))?(?:reply_serial=([\d]*))?'
m = re.split(regex, messages)
m = m[1:]                       # discard empty? text before first match
remember = dict()
while m:    # each match group is 9 capturing groups + 1 parameter group
    if m[0] == 'method call':
        print "C [{2},{4}] {5} {6}.{7}".format(*m),
        remember[m[4]] = m[6:8] # store interface+member for return
    if m[0] == 'method return':
        m[6:8] = remember[m[8]] # recall stored interface+member
        print "R [{3},{8}] {6}.{7}".format(*m),
    if m[0] == 'signal':
        print "S [{2}, {4}] {5} {6}.{7}".format(*m),
    # now handle parameters
    sep = "("
    for p in m[9].split('\n')[1:-1]:    # except empty string at start and end
        if p[-1] in "[](){}":           # with "encapsulations":
            p = p[-1]                   #   delete spaces, "array", "dict ..."
        p = re.sub('^\s*\w*\s*', '', p) # delete spaces and data type
        if p[-1] in "])}":
            sep = ''                    # no separator before closing
        print sep+p,
        sys.stdout.softspace=0
        if p[-1] in "[](){}":   sep = ''
        else:                   sep = ', '  # separator after data item
    print ")"
    m = m[10:]                  # delete the processed match group of 10

Вывод с вашими образцами данных:

C [:1.62,122] /org/freedesktop/filehandler/routing org.freedesktop.filehandler.routing.start (29877, 0)
R [:1.62,122] org.freedesktop.filehandler.routing.start (29877, 0)
C [:1.62,123] /org/freedesktop/filehandler/routing org.freedesktop.filehandler.routing.comment ("starting ..", "routing")
R [:1.62,123] org.freedesktop.filehandler.routing.comment (-23145)
S [:1.64, 124] /org/freedesktop/fileserver org.freedesktop.DBus.Properties.PropertiesChanged ("com.freedesktop.Systemserver", [("SystemTime", {12, 9, 0})][])
0 голосов
/ 25 апреля 2019

Можете ли вы предложить, как код может быть переписан для обработки построчно?

Здесь я изменил его соответствующим образом:

import re
import sys
regex = r'\b(signal|method call|method return)\b time=([\d,.]*) sender=([\w,.,:,(,), ]*) -> destination=([\w,.,:,(,), ]*) serial=([(,),\w]*) (?:path=([\w,\/]*); interface=([\w,.]*); member=([\w,_,-]*))?(?:reply_serial=([\d]*))?'
remember = dict()
sep = None
for line in open('dbusl.in'):
    m = re.match(regex, line)
    if m:
        if sep is not None: print ")"   # end the previous parameter group
        m = list(m.groups())        # each match is 9 capturing groups
        if m[0] == 'method call':
            print "C [{2},{4}] {5} {6}.{7}".format(*m),
            remember[m[4]] = m[6:8]     # store interface+member for return
        if m[0] == 'method return':
            m[6:8] = remember.pop(m[8]) # recall stored interface+member
            print "R [{3},{8}] {6}.{7}".format(*m),
        if m[0] == 'signal':
            print "S [{2}, {4}] {5} {6}.{7}".format(*m),
        sep = "("
    else:
        p = line.rstrip()               # now handle parameters
        if p[-1] in "[](){}":           # with "encapsulations":
            p = p[-1]                   #   delete spaces, "array", "dict ..."
        p = re.sub('^\s*\w*\s*', '', p) # delete spaces and data type
        if p[-1] in "])}":
            sep = ''                    # no separator before closing
        print sep+p,
        sys.stdout.softspace=0
        if p[-1] in "[](){}":   sep = ''
        else:                   sep = ', '  # separator after data item
print ")"                       # end the previous parameter group

Обратите внимание, что я также изменилm[6:8] = remember[m[8]] до m[6:8] = remember.pop(m[8]), чтобы освободить память, которая больше не нужна интерфейс + элемент данные.

0 голосов
/ 23 апреля 2019

Если вам абсолютно необходимо использовать dbus-monitor, вероятно, лучше использовать режим вывода PCAP, передав ему параметр --pcap. Это выводит в хорошо документированном структурированном формате , который может быть прочитан как libpcap .

...