有没有办法从Object.inspect方法的输出重新创建一个对象?

时间:2016-03-11 18:04:23

标签: ruby elasticsearch marshalling logstash

在使用开源ELK堆栈时,我们遇到了一个问题,其中一个Logstash输入snmptrap以一种对我们来说无法使用的方式格式化数据。在SNMPv1_Trap类中,有一个名为agent_address的实例变量,它存储为SNMP::IpAddress。对于熟悉SNMP工作方式的人来说,代理地址对于确定在网络上使用陷阱中继时SNMP陷阱的来源非常重要。

当您在收到陷阱时查看Logstash生成的事件时,可以看到问题。主要是,inspect变量的agent_address方法是转储与任何有效内容不匹配的数据。

示例事件看起来像这样:

#<SNMP::SNMPv1_Trap:0x2db53346 @enterprise=[1.3.6.1.4.1.6827.10.17.3.1.1.1], @timestamp=#<SNMP::TimeTicks:0x2a643dd1 @value=0>, @varbind_list=[#<SNMP::VarBind:0x2d5043a5 @name=[1.0], @value=#<SNMP::Integer:0x29fb6a4a @value=1>>], @specific_trap=1000, @source_ip=\"192.168.87.228\", @agent_addr=#<SNMP::IpAddress:0x227a4011 @value=\"\\xC0\\xA8V\\xFE\">, @generic_trap=6>

然而,我们知道,SNMP :: SNMPv1_Trap中使用的IpAddress对象能够返回一个格式很好的字符串,表示它正在存储的IPv4地址。

例如:

require 'snmp'
include SNMP
address = IpAddress.new(192.168.86.254)
puts address

将产生192.168.86.254而不是:

require 'snmp'
include SNMP
address = IpAddress.new(192.168.86.254)
puts address.inspect

将产生:

#<SNMP::IpAddress:0x0000000168ae88 @value="\xC0\xA8V\xFE">

这是未覆盖.inspect方法的对象的预期行为。

显然@value中的IPv4地址对我们没用,它只有三个有效的十六进制序列(xC0 = 192,xA8 = 168,xFE = 254),并且还包含无效的十六进制序列('V')。每当表示IPv4地址的八位字节串也作为变量绑定发送时,也会出现同样的情况,这表明存在一些奇怪的编码。

不幸的是,除了编写我们自己的SNMP输入外,没有对该对象的接口级访问权限。我们通过'event'接收的对象包含inspect字符串,而不是对象本身。因此,获取所需信息的最简单方法是重建SNMPv1_Trap对象,然后通过Object.#send自己调用它。

如果我有Object.#inspect返回的原始的,未格式化的和默认的字符串转储,有没有办法在物理上重新创建用于实时检查转储的对象?

例如,给定字符串转储:

#<Integer:0x2737476 @value=1>

是否可以使用值为1?的字段重新创建一个Integer对象。如果这是可能的,还有一种方法以相同的方式重新创建嵌套对象吗?例如,给定字符串:

#<SNMP::SNMPv1_Trap:0x2ef73621 @value=1, @agent_address=#<SNMP::IpAddress:0x0000000168ae88 @value="\xC0\xA8V\xFE">>

是否可以拥有一个如下所示的对象?

SNMP::SNMPv1_Trap{
  @value : 1
  @agent_address : SNMP::IpAddress{
      @value : 1
  }
}

1 个答案:

答案 0 :(得分:0)

  

如果我有Object#inspect返回的原始的,未格式化的和默认的字符串转储,有没有办法在物理上重新创建用于实时检查转储的对象?

没有。 inspect旨在用于人类阅读的调试目的。

不保证机器可读。不同的Ruby版本不保证相同。不保证在不同的Ruby实现中是相同的。在实现相同Ruby版本的相同Ruby实现的不同版本中甚至不能保证相同。哎呀,我甚至认为两次运行都不能保证相同!

它不是序列化格式。

有很多专门针对Ruby(Marshal)或一般(XML,YAML,JSON,当然还有ASN.1)的序列化格式,但inspect不是它。