【问题标题】:python multiprocessing to receive snmp alertspython多处理接收snmp警报
【发布时间】:2014-02-27 10:21:35
【问题描述】:

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

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

我的另一种选择是写入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()

【问题讨论】:

  • 我的代码可以工作了。我在trapReceiver 中创建了cbFun 一个嵌套函数。 queue 变量对主进程是本地的,并传递给trapReceiver(q)。我也打算添加Lock,这样父进程和子进程的输出就不会混淆。

标签: python queue multiprocessing snmp pysnmp


【解决方案1】:

您可以尝试使用闭包将 Queue 对象传递给 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() 本地范围内的队列对象,那么想法是。

【讨论】:

  • 我意识到我的问题是处理变量范围。现在,我在TrapReceiver 中创建了cbFun 一个嵌套函数,它解决了我认为的问题。这是一个好主意吗?该代码目前正在运行。但如果我遇到更多问题,我一定会尝试你的解决方案。谢谢!
  • 感谢您的提示。我在代码中遇到类似情况的其他地方使用了它。效果很好。
【解决方案2】:

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

【讨论】:

  • 我认为subprocess 主要用于在shell 中运行非python 代码或命令。但是,我尝试将trapreceiver() 放在一个单独的文件中并运行它。它没有用。子进程退出而不等待接收陷阱。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-21
  • 1970-01-01
  • 2018-06-24
  • 2017-02-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多