间隔读取标准输出

Read stdout in an interval

上下文

我正在使用 tcpdump 来观察数据包。我在 60 秒内遍历实时和聚合数据中的每一行。

然后,60 秒后,我更新了数据库。我需要每 60 秒不断获取数据,即使没有数据包(通过插入空数据)。

问题

如果没有互联网或数据包,循环不会继续,我必须等待 x 秒才能获得下一个输出。问题是间隔可以> 60s。

当前代码

ts = int(time.time())

p = subprocess.Popen(
    (
        "tcpdump",
        "-neqli",
        "eth0"
    ),
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE,
    universal_newlines=True,
)

interval = 60
sessions = {}

for row in iter(p.stdout.readline, ""):
    # Do some work, aggregate data
    splited_row = row.split(" ")
    log_ts = splited_row[0]
    sessions[log_ts] = "Anything"
    if int(time.time()) - interval > ts:
        # Insert in database
        insert_in_database(sessions)
    ts = int(time.time())

解决方案

感谢@Gerd,我不得不使用线程和队列。

在生产者中,我使用上面没有时间部分的代码。首先,我获取当前队列数据以在每个新输入时更新它。然后我没有插入,而是将聚合数据放入其中。

然后,我的消费者每 60 秒循环一次,获取队列数据并插入。

我建议使用带有两个线程的生产者-消费者方法:Here is a complete example(使用随机整数值而不是字符串)。

在您的情况下,生产者线程将从子进程读取 tcpdump 输出并将结果放入队列中,消费者线程将每 60 秒查看一次队列并找到一些数据或队列是空的。所以你的消费者线程主循环看起来像这样:

while True:
    if not q.empty():
        item = q.get()
        print('Getting ' + str(item) + ' : ' + str(q.qsize()) + ' items in queue')
        # insert data into database
    else:
        print('No data')
        # insert null data into database
    time.sleep(60.0)