Ruby nil:NilClass 的未定义方法“[]”
Ruby undefined method `[]' for nil:NilClass
我正在尝试让 nagios 检查 BBU(电池备份单元),我有一个名为 check_bbu
的 ruby 脚本
#!/usr/bin/ruby
require 'json'
output = %x{/usr/sbin/storcli /c0/bbu show j}
begin
j = JSON.parse(output)
result = j["Controllers"][0]["Command Status"]["Status"]
status = j["Controllers"][0]["Response Data"]["BBU_Info"][0]["State"]
rescue Exception => e
puts "CRITICAL: error reading BBU status: #{e}"
exit 2
end
if result != 'Success'
puts "CRITICAL: command not successful, result: #{result}"
exit 2
end
if status != 'Optimal'
puts "CRITICAL: BBU not optimal, status is #{status}"
exit 2
end
puts "OK: BBU is optimal"
但是当我 运行 这个插件时,我遇到了以下错误,
$ ./check_nrpe -u -t 30 -H foo.example.com -c check_bbu
CRITICAL: error reading BBU status: undefined method `[]' for nil:NilClass
我做错了什么?
您的代码似乎在
中断
j = JSON.parse(output)
result = j["Controllers"][0]["Command Status"]["Status"]
status = j["Controllers"][0]["Response Data"]["BBU_Info"][0]["State"]
你应该检查哪一行
j == nil
,你想要j["Controllers"]
result = j["Controllers"][0]["Command Status"]["Status"]
status = j["Controllers"][0]["Response Data"]["BBU_Info"][0]["State"]
导致 undefined method '[]' for nil:NilClass
首先显示 j
值,并确保 json 格式与您的代码匹配。
j = JSON.parse(output)
p j # display value
更新:
您的 json 格式应与您的代码匹配,否则会引发错误。
例如:
{
"Controllers": [
{
"Commandddd Status": { # format not match
"Status": "success"
}
}
]
}
# code and json format not match
j["Controllers"][0]["Command Status"] # nil
j["Controllers"][0]["Command Status"]["Status"]
=> nil["Status"] # boom!
例如我的评论,假设我们有正确的 JSON:
j = {"Controllers" => [{"Comand Status" => {"status" => 'ok'}}]}
=> {"Controllers"=>[{"Comand Status"=>{"status"=>"ok"}}]}
所以通过输入第一行,应该 return 正确的结果:
> j["Controllers"][0]["Comand Status"]["status"]
=> "ok"
但是也有可能写错JSON,例如:
j_e = {"Controllers" => []}
所以现在是 return 错误:
>j_e["Controllers"][0]["Comand Status"]["status"]
NoMethodError: undefined method `[]' for nil:NilClass
要解决它,你可以使用类似的东西:
def try data, keys # there we take arguments: data == j, and keys == array with keys
return data if data.nil? # there we check: if data, that we send == nil, for example j = nil, array = ['first', etc..] we should stop this method and return nil as result
value = data[keys.shift] # on this line we try to get some data from j ##keys.shift will delete first element from array that we send to this method and return as `key` for `data`, for example data['Controllers'] so keys now will looks like: [0, 'Comand Status', 'status']
unless keys.empty? #on this line we check if on the pred line we was used the last key and keys now looks like: [] we: *return value and if it's not empty we just **call this method 1 more time
try(value, keys) #**value = [{"Comand Status" => {"status" => 'ok'}}] and keys = [0, 'Comand Status', 'status']
else
value #*nil or value
end
end
j = {"Controllers"=>[{"Comand Status"=>{"status"=>"ok"}}]}
try(j, ['Controllers', 0, 'Comand Status', 'status'])
>'ok'
try j, ['Controllers', 1, 'Comand Status', 'status']
> nil
在您的代码中,这应该如下所示:
require 'json'
def try data, keys
return data if data.nil?
value = data[keys.shift]
unless keys.empty?
try(value, keys)
else
value
end
end
output = %x{/usr/sbin/storcli /c0/bbu show j}
begin
j = JSON.parse(output)
result = try(j, ["Controllers", 0, "Command Status", "Status"])
status = try(j, ["Controllers", 0, "Response Data", "BBU_Info", 0, "State"])
rescue Exception => e
puts "CRITICAL: error reading BBU status: #{e}"
exit 2
end
if result != 'Success'
puts "CRITICAL: command not successful, result: #{result}"
exit 2
end
if status != 'Optimal'
puts "CRITICAL: BBU not optimal, status is #{status}"
exit 2
end
puts "OK: BBU is optimal"
此外,对于 Ruby 2.3.0+
简单多了,只是:
j.dig("Controllers", 0, "Comand Status", "status")
我正在尝试让 nagios 检查 BBU(电池备份单元),我有一个名为 check_bbu
#!/usr/bin/ruby
require 'json'
output = %x{/usr/sbin/storcli /c0/bbu show j}
begin
j = JSON.parse(output)
result = j["Controllers"][0]["Command Status"]["Status"]
status = j["Controllers"][0]["Response Data"]["BBU_Info"][0]["State"]
rescue Exception => e
puts "CRITICAL: error reading BBU status: #{e}"
exit 2
end
if result != 'Success'
puts "CRITICAL: command not successful, result: #{result}"
exit 2
end
if status != 'Optimal'
puts "CRITICAL: BBU not optimal, status is #{status}"
exit 2
end
puts "OK: BBU is optimal"
但是当我 运行 这个插件时,我遇到了以下错误,
$ ./check_nrpe -u -t 30 -H foo.example.com -c check_bbu
CRITICAL: error reading BBU status: undefined method `[]' for nil:NilClass
我做错了什么?
您的代码似乎在
中断j = JSON.parse(output)
result = j["Controllers"][0]["Command Status"]["Status"]
status = j["Controllers"][0]["Response Data"]["BBU_Info"][0]["State"]
你应该检查哪一行
j == nil
,你想要j["Controllers"]
result = j["Controllers"][0]["Command Status"]["Status"]
status = j["Controllers"][0]["Response Data"]["BBU_Info"][0]["State"]
导致 undefined method '[]' for nil:NilClass
首先显示 j
值,并确保 json 格式与您的代码匹配。
j = JSON.parse(output)
p j # display value
更新:
您的 json 格式应与您的代码匹配,否则会引发错误。
例如:
{
"Controllers": [
{
"Commandddd Status": { # format not match
"Status": "success"
}
}
]
}
# code and json format not match
j["Controllers"][0]["Command Status"] # nil
j["Controllers"][0]["Command Status"]["Status"]
=> nil["Status"] # boom!
例如我的评论,假设我们有正确的 JSON:
j = {"Controllers" => [{"Comand Status" => {"status" => 'ok'}}]}
=> {"Controllers"=>[{"Comand Status"=>{"status"=>"ok"}}]}
所以通过输入第一行,应该 return 正确的结果:
> j["Controllers"][0]["Comand Status"]["status"]
=> "ok"
但是也有可能写错JSON,例如:
j_e = {"Controllers" => []}
所以现在是 return 错误:
>j_e["Controllers"][0]["Comand Status"]["status"]
NoMethodError: undefined method `[]' for nil:NilClass
要解决它,你可以使用类似的东西:
def try data, keys # there we take arguments: data == j, and keys == array with keys
return data if data.nil? # there we check: if data, that we send == nil, for example j = nil, array = ['first', etc..] we should stop this method and return nil as result
value = data[keys.shift] # on this line we try to get some data from j ##keys.shift will delete first element from array that we send to this method and return as `key` for `data`, for example data['Controllers'] so keys now will looks like: [0, 'Comand Status', 'status']
unless keys.empty? #on this line we check if on the pred line we was used the last key and keys now looks like: [] we: *return value and if it's not empty we just **call this method 1 more time
try(value, keys) #**value = [{"Comand Status" => {"status" => 'ok'}}] and keys = [0, 'Comand Status', 'status']
else
value #*nil or value
end
end
j = {"Controllers"=>[{"Comand Status"=>{"status"=>"ok"}}]}
try(j, ['Controllers', 0, 'Comand Status', 'status'])
>'ok'
try j, ['Controllers', 1, 'Comand Status', 'status']
> nil
在您的代码中,这应该如下所示:
require 'json'
def try data, keys
return data if data.nil?
value = data[keys.shift]
unless keys.empty?
try(value, keys)
else
value
end
end
output = %x{/usr/sbin/storcli /c0/bbu show j}
begin
j = JSON.parse(output)
result = try(j, ["Controllers", 0, "Command Status", "Status"])
status = try(j, ["Controllers", 0, "Response Data", "BBU_Info", 0, "State"])
rescue Exception => e
puts "CRITICAL: error reading BBU status: #{e}"
exit 2
end
if result != 'Success'
puts "CRITICAL: command not successful, result: #{result}"
exit 2
end
if status != 'Optimal'
puts "CRITICAL: BBU not optimal, status is #{status}"
exit 2
end
puts "OK: BBU is optimal"
此外,对于 Ruby 2.3.0+
简单多了,只是:
j.dig("Controllers", 0, "Comand Status", "status")