8

pysnmp フレームワークを使用して、snmp ウォークを実行していくつかの値を取得します。残念ながら、oidにとっては

1.3.6.1.21.69.1.5.8.1.2 (ドキュメント ケーブル デバイス MIB)

次のようなASCII文字が含まれているため、ここに正しく印刷できない奇妙な結果が得られますBEL ACK

repr を実行すると、次のようになります。

OctetString('\x07\xd8\t\x17\x03\x184\x00')

ただし、出力は次のようになります。

2008-9-23,3:24:52.0

形式は「DateAndTime」と呼ばれます。OctetString 出力を「人間が読める」日付/時刻に変換するにはどうすればよいですか?

4

3 に答える 3

17

形式の仕様については、こちらを参照してください。

A date-time specification. 
            field  octets  contents                  range
            -----  ------  --------                  -----
              1      1-2   year*                     0..65536
              2       3    month                     1..12
              3       4    day                       1..31
              4       5    hour                      0..23
              5       6    minutes                   0..59
              6       7    seconds                   0..60
                           (use 60 for leap-second)
              7       8    deci-seconds              0..9
              8       9    direction from UTC        '+' / '-'
              9      10    hours from UTC*           0..13
             10      11    minutes from UTC          0..59
* Notes:
            - the value of year is in network-byte order
            - daylight saving time in New Zealand is +13 For example, 
              Tuesday May 26, 1992 at 1:30:15 PM EDT would be displayed as:
                 1992-5-26,13:30:15.0,-4:0 
              Note that if only local time is known, then timezone
              information (fields 8-10) is not present.

サンプル データをデコードするには、次の簡単なワンライナーを使用できます。

>>> import struct, datetime
>>> s = '\x07\xd8\t\x17\x03\x184\x00'
>>> datetime.datetime(*struct.unpack('>HBBBBBB', s))
datetime.datetime(2008, 9, 23, 3, 24, 52)

上記の例は完璧とは言えません。サイズが考慮されておらず (このオブジェクトは可変サイズです)、タイムゾーン情報が欠落しています。また、フィールド 7 はデシ秒 (0..9) であり、timetuple[6] はマイクロ秒 (0 <= x < 1000000) であることに注意してください。正しい実装は、読者の課題として残しておきます。

[アップデート]

8 年後、この回答を修正してみましょう (私は怠け者ですか?):

import struct, pytz, datetime

def decode_snmp_date(octetstr: bytes) -> datetime.datetime:
    size = len(octetstr)
    if size == 8:
        (year, month, day, hour, minutes, 
         seconds, deci_seconds,
        ) = struct.unpack('>HBBBBBB', octetstr)
        return datetime.datetime(
            year, month, day, hour, minutes, seconds, 
            deci_seconds * 100_000, tzinfo=pytz.utc)
    elif size == 11:
        (year, month, day, hour, minutes, 
         seconds, deci_seconds, direction, 
         hours_from_utc, minutes_from_utc,
        ) = struct.unpack('>HBBBBBBcBB', octetstr)
        offset = datetime.timedelta(
            hours=hours_from_utc, minutes=minutes_from_utc)
        if direction == b'-':
            offset = -offset 
        return datetime.datetime(
            year, month, day, hour, minutes, seconds, 
            deci_seconds * 100_000, tzinfo=pytz.utc) + offset
    raise ValueError("The provided OCTETSTR is not a valid SNMP date")

タイムゾーンのオフセットが正しいかどうかはわかりませんが、テストするサンプルデータがありません。回答を修正するか、コメントで私に連絡してください。

于 2010-12-31T19:50:53.887 に答える
4

@Paulo Scardine: これは、非常によく似た問題を解決するためにオンラインで見つけた最良の答えでした。この回答でも問題を解決するのに少し時間がかかったので、より明確にするフォローアップの回答を投稿したいと思いました. (具体的には、異なる長さオプションを持つ日付の問題)。

次のコードは、サーバーに接続してシステム時間を取得し、それを文字列として出力してメソッドを示しています。

import netsnmp
import struct
oid = netsnmp.Varbind('hrSystemDate.0')
resp = netsnmp.snmpget(oid, Version=1, DestHost='<ip>', Community='public')
oct = str(resp[0])
# hrSystemDate can be either 8 or 11 units in length.
oct_len = len(oct)
fmt_mapping = dict({8:'>HBBBBBB', 11:'>HBBBBBBcBB'})
if oct_len == 8 or oct_len == 11:
    t = struct.unpack(fmt_mapping[oct_len], oct)
    print 'date tuple: %s' % (repr(t))
else:
    print 'invalid date format'

これが、このタイプのデータを操作しようとして同様の問題を抱えている他の人々に役立つことを願っています.

于 2012-01-10T19:47:38.640 に答える
2

恥知らずなプラグイン: Pycopia SNMP および SMI モジュールは、このオブジェクトやその他のオブジェクトを正しく処理します。 Pycopiaはソースからインストールされます。試す場合は mibsファイルを忘れないでください。

于 2010-12-31T21:54:09.693 に答える