有没有办法从其 Object.inspect 方法的输出中重新创建一个对象?
Is there any way to recreate an object from the output of its Object.inspect method?
在使用开源 ELK 堆栈时,我们 运行 遇到一个问题,其中一个 Logstash 输入 snmptrap 正在以我们无法使用的方式格式化数据。 SNMPv1_Trap class there is an instance variable called agent_address
which is stored as a SNMP::IpAddress内。对于任何熟悉 SNMP 工作方式的人来说,在网络上使用陷阱中继时,代理地址对于确定 SNMP 陷阱的来源非常重要。
当您查看 Logstash 在收到陷阱时生成的事件时,就会发现问题。主要是,agent_address
变量的 inspect
方法正在转储不匹配任何有效内容的数据。
示例事件看起来像这样:
#<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 对象能够 return 我们一个格式良好的字符串,表示它存储的 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' 收到的对象包含检查字符串,而不是对象本身。因此,获取我们所需信息的最简单明显的方法是重建 SNMPv1_Trap 对象,然后通过 Object.#send
.
进行我们自己的调用。
如果我有 return 由 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
}
}
If I have the raw, unformatted and default string dump returned by Object#inspect
, is there any way to physically recreate the object used to make this inspect dump on the fly?
没有。 inspect
旨在供人类阅读的调试目的。
不保证机器可读。不保证在不同的 Ruby 版本中是相同的。不保证在不同的 Ruby 实现中是相同的。它甚至不能保证在实现相同 Ruby 版本的相同 Ruby 实现的不同版本中是相同的。哎呀,我什至不认为它能保证两次运行都一样!
不是序列化格式
有很多专门针对 Ruby (Marshal
) 或通用格式(XML、YAML、JSON,当然还有 ASN.1)的序列化格式,但是 inspect
不是。
在使用开源 ELK 堆栈时,我们 运行 遇到一个问题,其中一个 Logstash 输入 snmptrap 正在以我们无法使用的方式格式化数据。 SNMPv1_Trap class there is an instance variable called agent_address
which is stored as a SNMP::IpAddress内。对于任何熟悉 SNMP 工作方式的人来说,在网络上使用陷阱中继时,代理地址对于确定 SNMP 陷阱的来源非常重要。
当您查看 Logstash 在收到陷阱时生成的事件时,就会发现问题。主要是,agent_address
变量的 inspect
方法正在转储不匹配任何有效内容的数据。
示例事件看起来像这样:
#<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 对象能够 return 我们一个格式良好的字符串,表示它存储的 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' 收到的对象包含检查字符串,而不是对象本身。因此,获取我们所需信息的最简单明显的方法是重建 SNMPv1_Trap 对象,然后通过 Object.#send
.
如果我有 return 由 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
}
}
If I have the raw, unformatted and default string dump returned by
Object#inspect
, is there any way to physically recreate the object used to make this inspect dump on the fly?
没有。 inspect
旨在供人类阅读的调试目的。
不保证机器可读。不保证在不同的 Ruby 版本中是相同的。不保证在不同的 Ruby 实现中是相同的。它甚至不能保证在实现相同 Ruby 版本的相同 Ruby 实现的不同版本中是相同的。哎呀,我什至不认为它能保证两次运行都一样!
不是序列化格式
有很多专门针对 Ruby (Marshal
) 或通用格式(XML、YAML、JSON,当然还有 ASN.1)的序列化格式,但是 inspect
不是。