当重试次数大于 0 且 ignore_failure 为真时,是否重复执行了 ruby_block?
Is a ruby_block executed repeatedly when retries is above 0 and ignore_failure is true?
有一个带有 ruby 方块的厨师食谱。 ruby 块一直执行到可以建立套接字连接(重试 10 次)。如果无法建立连接,ruby-block 不应失败 (ignore_failure)。
示例:
ruby_block 'wait for service' do
block do
require 'socket'
require 'timeout'
Timeout.timeout(2) do
s = TCPSocket.new('127.0.0.1', 8080)
s.close
end
end
retries 10
retry_delay 5
ignore_failure true
action :run
end
当 ignore_failure
设置为 true
时,chef 文档没有明确说明 ruby 块是否重复执行。
更新
当执行脚本并且没有服务在端口 8080 上侦听时,厨师食谱的执行在第一次尝试后继续,并显示以下消息:
ERROR: ruby_block[wait for service] (cookbook::wait_for_service line 1) had an error: Errno::ECONNREFUSED: Connection refused - connect(2) for "127.0.0.1" port 8080; ignore_failure is set, continuing
...
Error executing action run on resource 'ruby_block[wait for service]'
Errno::ECONNREFUSED
-------------------
Connection refused - connect(2) for "127.0.0.1" port 8080
...
由于 ruby_block 声明,我认为 ruby 在报告 ERROR
.
之前执行了 10 次
我的测试证明重试没有效果。该块仅执行一次,因为套接字连接失败。
我已经使用 Chef 版本 12.19.36 测试了您的场景,如果只指定了 ignore_failure
和 retries
[=应用 21=]ignore_failure 而忽略 retries。
这里的 Chef 文档也不清楚这种特定情况,因此无法解决您的问题。
无论如何,您可以解决手动实施 retries 和 retry_delay 逻辑,如下所示:
ruby_block 'wait for service' do
block do
require 'socket'
require 'timeout'
retry_delay = 5
retries = 10
1.upto(retries) do |n|
err_msg = ""
begin
Timeout::timeout(retry_delay) do
begin
s = TCPSocket.new('8.8.8.8', 52)
s.close
puts("Service is listening on")
break
rescue Errno::ECONNREFUSED
err_msg = "Port is open but no service is listening on"
rescue Errno::EHOSTUNREACH
err_msg = "Unable to connect to the service"
end
end
rescue Timeout::Error
err_msg = "Timeout reached"
end
if n == retries
raise "Unabled to reach server in #{retries} attempts"
else
puts "Failed to reach server on attempt [#{n}/#{retries}]. Cause is: [#{err_msg}]. Waiting #{retry_delay} seconds and retry."
sleep(retry_delay)
end
end
end
ignore_failure true
action :run
end
您还可以改进创建通用函数 execute_with_retry 的代码,并将 lambda 函数作为输入,以便在需要时在您的食谱中简单地重用此逻辑。
有一个带有 ruby 方块的厨师食谱。 ruby 块一直执行到可以建立套接字连接(重试 10 次)。如果无法建立连接,ruby-block 不应失败 (ignore_failure)。
示例:
ruby_block 'wait for service' do
block do
require 'socket'
require 'timeout'
Timeout.timeout(2) do
s = TCPSocket.new('127.0.0.1', 8080)
s.close
end
end
retries 10
retry_delay 5
ignore_failure true
action :run
end
当 ignore_failure
设置为 true
时,chef 文档没有明确说明 ruby 块是否重复执行。
更新
当执行脚本并且没有服务在端口 8080 上侦听时,厨师食谱的执行在第一次尝试后继续,并显示以下消息:
ERROR: ruby_block[wait for service] (cookbook::wait_for_service line 1) had an error: Errno::ECONNREFUSED: Connection refused - connect(2) for "127.0.0.1" port 8080; ignore_failure is set, continuing
...
Error executing action run on resource 'ruby_block[wait for service]'
Errno::ECONNREFUSED
-------------------
Connection refused - connect(2) for "127.0.0.1" port 8080
...
由于 ruby_block 声明,我认为 ruby 在报告 ERROR
.
我的测试证明重试没有效果。该块仅执行一次,因为套接字连接失败。
我已经使用 Chef 版本 12.19.36 测试了您的场景,如果只指定了 ignore_failure
和 retries
[=应用 21=]ignore_failure 而忽略 retries。
这里的 Chef 文档也不清楚这种特定情况,因此无法解决您的问题。
无论如何,您可以解决手动实施 retries 和 retry_delay 逻辑,如下所示:
ruby_block 'wait for service' do
block do
require 'socket'
require 'timeout'
retry_delay = 5
retries = 10
1.upto(retries) do |n|
err_msg = ""
begin
Timeout::timeout(retry_delay) do
begin
s = TCPSocket.new('8.8.8.8', 52)
s.close
puts("Service is listening on")
break
rescue Errno::ECONNREFUSED
err_msg = "Port is open but no service is listening on"
rescue Errno::EHOSTUNREACH
err_msg = "Unable to connect to the service"
end
end
rescue Timeout::Error
err_msg = "Timeout reached"
end
if n == retries
raise "Unabled to reach server in #{retries} attempts"
else
puts "Failed to reach server on attempt [#{n}/#{retries}]. Cause is: [#{err_msg}]. Waiting #{retry_delay} seconds and retry."
sleep(retry_delay)
end
end
end
ignore_failure true
action :run
end
您还可以改进创建通用函数 execute_with_retry 的代码,并将 lambda 函数作为输入,以便在需要时在您的食谱中简单地重用此逻辑。