Scapy奇怪的Python内存使用

Scapy奇怪的Python内存使用,python,mysql,sqlalchemy,Python,Mysql,Sqlalchemy,我编写了一个脚本,通过SQLAlchemy将mac地址从pcapy记录到mysql中。我最初使用的是纯sqlite3,但很快就意识到需要更好的东西,所以这个周末我重写了所有数据库对话,以符合SQLAlchemy。一切正常,数据进出。我认为sessionmaker()对于管理数据库中的所有会话非常有用 关于内存消耗,我看到了一个奇怪的现象。我开始写剧本。。。它收集并将所有数据写入数据库。。。但每2-4秒,内存消耗就会增加1兆字节。目前我所说的记录很少,少于100行 脚本序列: 脚本开始 SQLAl

我编写了一个脚本,通过SQLAlchemy将mac地址从pcapy记录到mysql中。我最初使用的是纯sqlite3,但很快就意识到需要更好的东西,所以这个周末我重写了所有数据库对话,以符合SQLAlchemy。一切正常,数据进出。我认为sessionmaker()对于管理数据库中的所有会话非常有用

关于内存消耗,我看到了一个奇怪的现象。我开始写剧本。。。它收集并将所有数据写入数据库。。。但每2-4秒,内存消耗就会增加1兆字节。目前我所说的记录很少,少于100行

脚本序列:

  • 脚本开始
  • SQLAlchemy将mac_addr列读入maclist[]
  • scapy获取packet>如果新的_mac在maclist[]中
  • 如果是真的?仅将时间戳写入mac=newmac的时间戳列。回到步骤2

    如果是假的?然后将新的mac写入DB。清除maclist[]并再次调用步骤2

    在1h30m之后,我的内存占用为1027MB(RES)和1198MB(VIRT),1表数据库(MySQL)中有124行

    Q:这是否会导致每次从DB清理并重新填充maclist[]呢?

    Q:当达到系统最大内存时会发生什么情况?

    任何想法或建议都将非常感谢

    从数据库mac\u addr列填充列表[]的相关段的内存\u探查器输出

    Line #    Mem usage    Increment   Line Contents
    ================================================
       123 1025.434 MiB    0.000 MiB   @profile
       124                             def sniffmgmt(p):
       125                              global __mac_reel
       126                              global _blacklist
       127 1025.434 MiB    0.000 MiB    stamgmtstypes = (0, 2, 4)
       128 1025.434 MiB    0.000 MiB    tmplist = []
       129 1025.434 MiB    0.000 MiB    matching = []
       130 1025.434 MiB    0.000 MiB    observedclients = []
       131 1025.434 MiB    0.000 MiB    tmplist = populate_observed_list()
       132 1025.477 MiB    0.043 MiB    for i in tmplist:
       133 1025.477 MiB    0.000 MiB          observedclients.append(i[0])
       134 1025.477 MiB    0.000 MiB    _mac_address = str(p.addr2)
       135 1025.477 MiB    0.000 MiB    if p.haslayer(Dot11):
       136 1025.477 MiB    0.000 MiB        if p.type == 0 and p.subtype in stamgmtstypes:
       137 1024.309 MiB   -1.168 MiB            _timestamp = atimer()
       138 1024.309 MiB    0.000 MiB            if p.info == "":
       139 1021.520 MiB   -2.789 MiB                        _SSID = "hidden"
       140                                          else:
       141 1024.309 MiB    2.789 MiB                        _SSID = p.info
       142                                      
       143 1024.309 MiB    0.000 MiB            if p.addr2 not in observedclients:
       144 1018.184 MiB   -6.125 MiB                    db_add(_mac_address, _timestamp, _SSID)
       145 1018.184 MiB    0.000 MiB                    greetings()
       146                                      else:
       147 1024.309 MiB    6.125 MiB                add_time(_mac_address, _timestamp)
       148 1024.309 MiB    0.000 MiB                observedclients = [] #clear the list
       149 1024.309 MiB    0.000 MiB                observedclients = populate_observed_list() #repopulate the list
       150 1024.309 MiB    0.000 MiB                greetings()
    

    您将看到有问题的列表是ObservedClient

    如果没有代码,很难说什么,假设它不是SQLAlchemy或scapy中的漏洞,而不是您的代码中的漏洞(似乎不太可能)

    你似乎知道泄漏可能发生在哪里,做一些事情看看你是否正确


    一旦python进程占用了足够的内存,您可能会得到一个
    MemoryError
    异常。

    正如您可以看到的那样,探查器输出建议您在结束时使用更少的内存,因此这并不代表您的情况

    深入挖掘的一些方向: 1) 添加时间(为什么会增加内存使用?) 2) db_add(为什么会减少内存使用?缓存?关闭/打开db连接?发生故障时会发生什么情况?) 3) 填充_-observed_列表(返回值对于垃圾收集是否安全?是否存在某些发生特定异常的数据包?)

    另外,如果您嗅探到的数据包超过了代码能够处理的数据包数,那么会发生什么情况呢


    我将分析这3个功能并分析可能的异常/故障。

    谢谢大家的指导。我想我设法解决了日益增长的内存消耗问题

    A:如我所知,代码逻辑在内存消耗中扮演着非常重要的角色。
    如果你看一下我的第一个问题中的memory_profiler输出,我将第131-133行移到了第136行的If语句中。这似乎不会如此频繁地增加记忆。现在,我需要对populate_observedlist()进行进一步优化,以避免浪费太多内存

    我设法找到了内存消耗的实际原因。是斯卡皮自己。默认情况下,Scapy设置为存储它捕获的所有数据包。但是你可以禁用它

    禁用:

    sniff(iface=interface, prn=sniffmgmt, store=0)
    
    sniff(iface=interface, prn=sniffmgmt, store=1)
    
    启用:

    sniff(iface=interface, prn=sniffmgmt, store=0)
    
    sniff(iface=interface, prn=sniffmgmt, store=1)
    

    多亏了

    没有代码很难说什么,假设它不是SQLAlchemy或scapy中的漏洞,而不是代码中的漏洞(似乎不太可能)。你似乎知道泄漏可能发生在哪里,做一些事情看看你是否正确。一旦python进程占用了足够的内存,可能会出现
    MemoryError
    异常。我一直在使用python中的memory_profiler-m选项来查看原因,但是我看到的没有意义,所以让我运行它并发布结果。我在使用列表的地方上传了探查器输出。