【问题标题】:Read stdout in an interval间隔读取标准输出
【发布时间】:2021-01-19 10:31:05
【问题描述】:

上下文

我正在使用 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 秒循环一次,获取队列数据并插入。

【问题讨论】:

    标签: python popen tcpdump


    【解决方案1】:

    我建议使用带有两个线程的生产者-消费者方法: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)
    

    【讨论】:

    • 这看起来是一个很好的解决方案,但我一次只能得到一个项目。这个想法是在 60 年代存储所有内容,然后一次又一次地对其进行迭代。而且,我不能使用 sleep 在消费类中工作
    • 您当然可以在队列中存储多个项目,然后每 60 秒在消费者端检索所有项目(例如 for i in range(q.qsize()) 或类似的)。为什么使用sleep 会出现问题?它应该只暂停消费者循环(在线程中运行)。
    • 我的错,我之前有过一段时间。成功了,非常感谢!
    猜你喜欢
    • 2014-07-08
    • 2013-02-24
    • 1970-01-01
    • 2016-01-14
    • 1970-01-01
    • 1970-01-01
    • 2012-06-08
    • 1970-01-01
    • 2011-01-08
    相关资源
    最近更新 更多