用于接收snmp警报的python多处理

用于接收snmp警报的python多处理,python,queue,multiprocessing,snmp,pysnmp,Python,Queue,Multiprocessing,Snmp,Pysnmp,我希望我的代码能够接收SNMP警报。我正在使用python的pysnmp模块。我正在为陷阱侦听器创建一个新进程。我正在使用多处理模块。陷阱侦听器接收snmp警报消息并将其发送到我的主进程,主进程将对它们进行一些计算。但如何将消息数据传递给父进程?我想创建一个队列。但是由于snmp数据是由函数cbFun()接收的,我不知道如何将其传递给trapreciver()。简单的返回函数不起作用 我想我可以使队列成为一个全局变量。这是个好主意吗 我的另一种选择是在cbFun中写入文件,然后在我的主进程中从中

我希望我的代码能够接收SNMP警报。我正在使用python的
pysnmp
模块。我正在为陷阱侦听器创建一个新进程。我正在使用
多处理
模块。陷阱侦听器接收snmp警报消息并将其发送到我的主进程,主进程将对它们进行一些计算。但如何将消息数据传递给父进程?我想创建一个队列。但是由于snmp数据是由函数
cbFun()
接收的,我不知道如何将其传递给
trapreciver()
。简单的返回函数不起作用

我想我可以使队列成为一个全局变量。这是个好主意吗

我的另一种选择是在
cbFun
中写入文件,然后在我的主进程中从中读取

最好的方法是什么

当我执行下面给出的代码时,子进程正在打印收到的snmp消息,但我无法从父进程打印它。我做错了什么

from pysnmp.entity import engine, config
from pysnmp.carrier.asynsock.dgram import udp, udp6
from pysnmp.entity.rfc3413 import ntfrcv
from multiprocessing import Process
import Queue

q = Queue.Queue()

def trapListener():
    # Create SNMP engine with autogenernated engineID and pre-bound
    # to socket transport dispatcher

    snmpEngine = engine.SnmpEngine()

    # Transport setup

    # UDP over IPv4
    config.addSocketTransport(
        snmpEngine,
        udp.domainName,
        udp.UdpTransport().openServerMode(('10.94.175.171', 162))
    )

    # SNMPv1/2c setup

    # SecurityName <-> CommunityName mapping
    config.addV1System(snmpEngine,'my-area', 'public')


    # Register SNMP Application at the SNMP engine
    ntfrcv.NotificationReceiver(snmpEngine, cbFun)

    snmpEngine.transportDispatcher.jobStarted(1) # this job would never finish

    # Run I/O dispatcher which would receive queries and send confirmations
    try:
        snmpEngine.transportDispatcher.runDispatcher()
    except:
        snmpEngine.transportDispatcher.closeDispatcher()
        raise
# Callback function for receiving notifications

def cbFun(snmpEngine,stateReference,
              contextEngineId, contextName,
              varBinds,
              cbCtx):
    (transportDomain, transportAddress ) = snmpEngine.msgAndPduDsp.getTransportInfo(stateReference)

    f=open('eventDescriptions.txt','r')
    print('Notification from %s, ContextEngineId "%s", ContextName "%s"' % (
                transportAddress, contextEngineId.prettyPrint(),
                contextName.prettyPrint()))

    for name, val in varBinds:
        if name.prettyPrint()=="1.3.6.1.4.1.674.10892.5.3.1.2.0":
            print('child: %s' % (val.prettyPrint()))
            q.put(val.prettyPrint())

if __name__=="__main__":
    p=Process(target=trapListener, args=(child_conn,))
    p.start()
    print "parent: ", q.get()
    p.join()
来自pysnmp.entity导入引擎,配置
从pysnmp.carrier.asynsock.dgram导入udp、udp6
从pysnmp.entity.rfc3413导入ntfrcv
从多处理导入进程
导入队列
q=队列。队列()
def trapListener():
#使用自动生成的engineID和预绑定创建SNMP引擎
#到套接字传输调度器
snmpEngine=engine.snmpEngine()
#传输设置
#IPv4上的UDP
config.addSocketTransport(
snmpEngine,
udp.domainName,
udp.udptTransport().openServerMode(('10.94.175.171',162))
)
#SNMPv1/2c设置
#SecurityName社区名称映射
config.addv1系统(snmpEngine、'my-area'、'public')
#在SNMP引擎上注册SNMP应用程序
ntfrcv.通知接收器(snmpEngine、cbFun)
snmpEngine.transportDispatcher.jobStarted(1)#此作业永远不会完成
#运行I/O调度程序,它将接收查询并发送确认
尝试:
snmpEngine.transportDispatcher.runDispatcher()
除:
snmpEngine.transportDispatcher.closeDispatcher()
提升
#用于接收通知的回调函数
def cbFun(snmpEngine、stateReference、,
contextEngineId,contextName,
瓦宾德,
cbCtx):
(transportDomain,transportAddress)=snmpEngine.msgandpudsp.getTransportInfo(stateReference)
f=打开('eventDescriptions.txt','r')
打印('来自%s、ContextEngineId“%s”、ContextName“%s”的通知%(
transportAddress,contextEngineId.prettyPrint(),
contextName.prettyPrint())
varBinds中的val作为名称:
如果name.prettyPrint()=“1.3.6.1.4.1.674.10892.5.3.1.2.0”:
打印('子项:%s'(val.prettyPrint()))
q、 put(val.prettyPrint())
如果名称=“\uuuuu main\uuuuuuuu”:
p=进程(target=trapListener,args=(子连接)
p、 开始()
打印“父项:”,q.get()
p、 加入

我不确定,但使用子流程模块可能会更简单。
您可以使用subprocess.Popen创建一个新流程,然后使用communicate方法向该流程发送数据。

您可以尝试使用闭包将队列对象传递给cbFun。大概是这样的:

def getCbFun(queue): # closure
    def cbFun(snmpEngine,stateReference,
          contextEngineId, contextName,
          varBinds,
          cbCtx):
        ...
        queue.add(varBinds)
        ...
    return cbFun

...

# Shared queue object
queue = Queue()

# Register SNMP Application at the SNMP engine
ntfrcv.NotificationReceiver(snmpEngine, getCbFun(queue))

...

因此,如果cbFun()将使用getCbFun()的局部作用域中的队列对象,那么它不是全局的。

我认为
子流程
主要用于在shell中运行非python代码或命令。但是,我尝试了一下,将
trapreciver()
放在一个单独的文件中并运行它。它不起作用。子进程在不等待接收陷阱的情况下退出。我让代码正常工作。我在
trapreciver
中创建了
cbFun
嵌套函数。队列变量被设置为主进程的本地变量,并传递给
trapreciver(q)
。我还打算添加
Lock
,这样父进程和子进程的输出就不会混淆。我意识到我的问题是处理变量范围。现在,我在
trapreciver
中创建了
cbFun
嵌套函数,解决了我认为的问题。这是个好主意吗?代码目前正在运行。但是如果我面临更多的问题,我一定会尝试你的解决方案。谢谢谢谢你的提示。我在代码的其他地方使用了它,在那里我遇到了类似的情况。它工作得很好。