2

私はこのコードを持っています:

from twisted.internet import reactor
from twisted.internet import defer, task
from pysnmp.entity import engine, config
from pysnmp.carrier.twisted import dispatch
from pysnmp.carrier.twisted.dgram import udp
from pysnmp.entity.rfc3413.twisted import cmdgen


import __webimport__
import tools.config
from tools.database import makedsn
import psycopg2


def cmp_varBinds(varBind, varName):
    if varName[0] in str(varBind[0]):
        return True


def cbFun(cbCtx, ip, varNames):
    (errorIndication, errorStatus, errorIndex, varBinds) = cbCtx
    if varBinds and any(map(cmp_varBinds, varBinds[0], varNames)):
        print ip, [str(x[1]) for x in varBinds[0]]
        df = defer.Deferred()
        df.addCallback(cbFun, ip=ip, varNames=varNames)
        return df  # This also indicates that we wish to continue walkin


def parallel(iterable, count, callable, *args, **named):
    coop = task.Cooperator()
    work = (callable(elem, *args, **named) for elem in iterable)
    return defer.DeferredList([coop.coiterate(work) for i in xrange(count)])





def fetch(host):
    id, ip, community, hc = host
    snmpEngine = engine.SnmpEngine()
    snmpEngine.registerTransportDispatcher(dispatch.TwistedDispatcher())
    config.addV1System(snmpEngine, 'test-agent', community)
    config.addTargetParams(snmpEngine, 'myParams', 'test-agent', 'noAuthNoPriv', 1)

    config.addTargetAddr(
                     snmpEngine, 'myRouter', config.snmpUDPDomain,
                     (ip, 161), 'myParams', timeout=1
    )

    # Transport
    config.addSocketTransport(
                          snmpEngine,
                          udp.domainName,
                          udp.UdpTwistedTransport().openClientMode()
    )

    getCmdGen = cmdgen.NextCommandGenerator()
    varNames = [('1.3.6.1.2.1.2.2.1.11', None),
            ('1.3.6.1.2.1.2.2.1.12', None),
            ('1.3.6.1.2.1.2.2.1.13', None),
            ('1.3.6.1.2.1.2.2.1.14', None)]
    df = getCmdGen.sendReq(snmpEngine, 'myRouter', varNames)
    df.addCallback(cbFun, ip=ip, varNames=varNames)
    return df


dsn = makedsn(tools.config.main_db)
connection = psycopg2.connect(dsn)
cursor = connection.cursor()
cursor.execute("""SELECT e.id, e.ip, e.snmpcomm, e.hccnt
           FROM snmp_ports sp, equipment e
           WHERE e.snmp = 'Y' and sp.equipment = e.id
           GROUP BY e.id,e.ip,e.snmpcomm,e.hccnt
           ORDER BY e.id""")
hosts = cursor.fetchall()


finished = parallel(hosts, len(hosts), fetch)
finished.addErrback(log.err)
finished.addCallback(lambda ign: reactor.stop())
reactor.run()

データベースから 4000 のホストを取得し、それぞれに問い合わせます。SQLクエリで制限1000を設定すると、正常に機能します。しかし、ホストが 1000 を超えると、エラーが発生します。

Unhandled Error
Traceback (most recent call last):
  File "crawler.py", line 98, in <module>

  File "/home/kalombo/.virtualenvs/dev/local/lib/python2.7/site-packages/twisted/internet/base.py", line 1192, in run

  File "/home/kalombo/.virtualenvs/dev/local/lib/python2.7/site-packages/twisted/internet/base.py", line 1201, in mainLoop

--- <exception caught here> ---
  File "/home/kalombo/.virtualenvs/dev/local/lib/python2.7/site-packages/twisted/internet/base.py", line 824, in runUntilCurrent

  File "/home/kalombo/.virtualenvs/dev/local/lib/python2.7/site-packages/pysnmp/carrier/base.py", line 52, in _cbFun

  File "/home/kalombo/.virtualenvs/dev/local/lib/python2.7/site-packages/pysnmp/entity/engine.py", line 64, in __receiveMessageCbFun

  File "/home/kalombo/.virtualenvs/dev/local/lib/python2.7/site-packages/pysnmp/proto/rfc3412.py", line 274, in receiveMessage

  File "/home/kalombo/.virtualenvs/dev/local/lib/python2.7/site-packages/pysnmp/smi/builder.py", line 299, in importSymbols

  File "/home/kalombo/.virtualenvs/dev/local/lib/python2.7/site-packages/pysnmp/smi/builder.py", line 270, in loadModules

pysnmp.smi.error.SmiError: MIB file "__SNMPv2-MIB.py[co]" not found in search path

そして、スクリプトが停止します。なぜこれが起こっているのですか?

4

2 に答える 2

2

これが同時実行レベルを上げたときにのみ発生する場合は、プラットフォームで一度に開くことができるファイル数の制限に達した可能性があります。開いている各ソケットは、(ファイルシステムからの) 「通常の」ファイルを開く場合と同様に、この制限にカウントされます。

許可されたファイルをすべて使い切ると、Python はモジュールのソース コードをディスクから読み取ることができなくなります。これは、そのプラットフォームがモジュールを開くことを許可しないためです。

(もしそうなら) pysnmp が実際の例外を処理し、詳細を隠す新しい例外を再発生させるため、これがこの場合に起こっていることであることは完全には明らかではありません。

これが問題である場合は、開いているファイルの制限を上げることで対処できます。ほとんどの場合、次のコマンドを実行してこれを行うことができます。

$ ulimit -Sn 2048

その制限を制御する方法の詳細については、 ulimit (インターネットhelp ulimit上のシェル内) を参照してください。

于 2013-10-18T11:34:51.570 に答える
2

使用しているpysnmpは何ですか?最新の pysnmp リリースを使用していることを確認してください。

補足として-GET操作ごとに[重い] SnmpEngineを再初期化するように見えるため、アプローチは非常に非効率的です。より良い方法は、プロセス/スレッドごとに 1 つの永続的な SnmpEngine インスタンスを保持することです。

于 2013-10-18T07:56:07.440 に答える