Python 正则表达式解析日志文件

57 阅读5分钟

我们需要解析一个电子邮件发送日志文件(获取消息 ID 的 SMTP 回复),该日志文件类似于以下内容:

Nov 12 17:26:57 zeus postfix/smtpd[23992]: E859950021DB1: client=pegasus.os[172.20.19.62]
Nov 12 17:26:57 zeus postfix/cleanup[23995]: E859950021DB1: message-id=a92de331-9242-4d2a-8f0e-9418eb7c0123
Nov 12 17:26:58 zeus postfix/qmgr[22359]: E859950021DB1: from=<system@directoperation.de>, size=114324, nrcpt=1 (queue active)
Nov 12 17:26:58 zeus postfix/smtp[24007]: certificate verification failed for mx.elutopia.it[62.149.128.160]:25: untrusted issuer /C=US/O=RTFM, Inc./OU=Widgets Division/CN=Test CA20010517
Nov 12 17:26:58 zeus postfix/smtp[24007]: E859950021DB1: to=<mike@elutopia.it>, relay=mx.elutopia.it[62.149.128.160]:25, delay=0.89, delays=0.09/0/0.3/0.5, dsn=2.0.0, status=sent (250 2.0.0 d3Sx1m03q0ps1bK013Sxg4 mail accepted for delivery)
Nov 12 17:26:58 zeus postfix/qmgr[22359]: E859950021DB1: removed
Nov 12 17:27:00 zeus postfix/smtpd[23980]: connect from pegasus.os[172.20.19.62]
Nov 12 17:27:00 zeus postfix/smtpd[23980]: setting up TLS connection from pegasus.os[172.20.19.62]
Nov 12 17:27:00 zeus postfix/smtpd[23980]: Anonymous TLS connection established from pegasus.os[172.20.19.62]: TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)
Nov 12 17:27:00 zeus postfix/smtpd[23992]: disconnect from pegasus.os[172.20.19.62]
Nov 12 17:27:00 zeus postfix/smtpd[23980]: 2C04150101DB2: client=pegasus.os[172.20.19.62]
Nov 12 17:27:00 zeus postfix/cleanup[23994]: 2C04150101DB2: message-id=21e2f9d3-154a-3683-85d3-a7c52d429386
Nov 12 17:27:00 zeus postfix/qmgr[22359]: 2C04150101DB2: from=<system@directoperation.de>, size=53237, nrcpt=1 (queue active)
Nov 12 17:27:00 zeus postfix/smtp[24006]: ABE7C50001D62: to=<info@elvictoria.it>, relay=relay3.telnew.it[195.36.1.102]:25, delay=4.9, delays=0.1/0/4/0.76, dsn=2.0.0, status=sent (250 2.0.0 r9EFQt0J009467 Message accepted for delivery)
Nov 12 17:27:00 zeus postfix/qmgr[22359]: ABE7C50001D62: removed
Nov 12 17:27:00 zeus postfix/smtp[23998]: 2C04150101DB2: to=<peter@elgravo.ch>, relay=liberomx2.elgravo.ch[212.52.84.93]:25, delay=0.72, delays=0.07/0/0.3/0.35, dsn=2.0.0, status=sent (250 ok:  Message 2040264602 accepted)
Nov 12 17:27:00 zeus postfix/qmgr[22359]: 2C04150101DB2: removed

目前,我们从数据库中获取一个消息 ID(例如 a92de331-9242-4d2a-8f0e-9418eb7c0123),然后运行代码通过日志文件:

log_id = re.search (']: (.+?): message-id='+message_id, text).group(1)
sent_status = (re.search (']: '+log_id+'.*dsn=(.....)', text)

使用消息 ID 找到 log_id,然后使用 log_id 可以找到 SMTP 回复答案。这个方法可以正常工作,但是更好的方法是,如果软件遍历日志文件,获取消息 ID 和回复代码,然后更新数据库。但是我们不确定如何做到这一点?这个脚本必须每 2 分钟运行一次,并检查更新的日志文件。那么我们如何确保它记住它的位置,并且不会重复获取消息 ID 呢?

2、解决方案

为了解决这个问题,我们需要使用一个状态文件来跟踪我们已经处理过的消息 ID。我们可以通过以下步骤来实现:

  1. 创建一个状态文件,其中包含我们已经处理过的所有消息 ID。初始状态文件可以是一个简单的文本文件,其中包含已处理消息 ID 的列表。
  2. 每当我们运行脚本时,我们首先检查状态文件以查看我们已经处理过的消息 ID。如果我们遇到一个我们之前处理过的消息 ID,我们就跳过它。否则,我们将处理该消息 ID,并将其添加到状态文件中。
  3. 为了确保状态文件保持最新,我们可以在脚本的最后更新它。这将确保我们不会处理同一个消息 ID 两次。

下面是一个 Python 代码示例,演示如何使用状态文件来解析日志文件:

import os
import re

# 状态文件的路径
state_file_path = 'state.txt'

# 打开状态文件
with open(state_file_path, 'r+') as f:
    # 读取已处理过的消息 ID
    processed_message_ids = set(f.readlines())

# 打开日志文件
with open('log.txt', 'r') as f:
    # 遍历日志文件中的每行
    for line in f:
        # 查找消息 ID
        match = re.search(r'message-id=(.+?) ', line)
        if match:
            # 获取消息 ID
            message_id = match.group(1)

            # 如果消息 ID 已经处理过,则跳过
            if message_id in processed_message_ids:
                continue

            # 处理消息 ID
            # ...

            # 将消息 ID 添加到已处理过的消息 ID 列表中
            processed_message_ids.add(message_id)

            # 更新状态文件
            f.write(message_id + '\n')

# 关闭状态文件
f.close()

通过这种方法,我们可以确保脚本不会重复处理同一个消息 ID,并且状态文件始终保持最新。