当重试次数大于 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_failureretries [=应用 21=]ignore_failure 而忽略 retries

这里的 Chef 文档也不清楚这种特定情况,因此无法解决您的问题。

无论如何,您可以解决手动实施 retriesretry_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 函数作为输入,以便在需要时在您的食谱中简单地重用此逻辑。