Chef: mmake sure a service is listennig on network

自闭症网瘾萝莉.ら 提交于 2019-12-12 05:48:43

问题


I'm using this mongodb3 cookbook in order to install a mongodb instance.

I'm trying to perform an script when service starts:

execute "Add Mongo Users" do
  command "mongo #{host}:#{port} /tmp/mongo.setup.users.js"
  subscribes :run, 'service[mongod]', :delayed
end

I'm getting this error:

==> Expected process to exit with [0], but received '1'
==> ---- Begin output of mongo localhost:30158 /tmp/mongo.setup.users.js ----
==> STDOUT: MongoDB shell version v3.4.2
==> connecting to: localhost:30158
==> 2017-06-05T07:39:48.136+0000 W NETWORK  [thread1] Failed to connect to 127.0.0.1:30158, in(checking soc
ket for error after poll), reason: Connection refused
==> 2017-06-05T07:39:48.136+0000 E QUERY    [thread1] Error: couldn't connect to server localhost:30158, co
nnection attempt failed :

So, as you can see, service is not running yet when command is performed (I'm getting a network error).

I've took a look on cookbook repository code. According to this peace of code, the service is started...

Any ideas?


回答1:


As triggering the start of a service does not mean that it's immediately ready to accept connections, you need to wait for a bit of time.

  • A common approach is to add an additional, hardcoded delay, e.g.

    command "sleep 3; mongo.."
    

    Downside: 3 seconds might be enough on machine A, but not on machine B. (So put 20sec and you've solved it for 99.9% of the cases - but didn't become a better programmer ;-)).

  • A better approach can be e.g. seen in the jenkins cookbook's helper library:

    def wait_until_ready!
      Timeout.timeout(timeout, JenkinsTimeout) do
        begin
          open(endpoint)
        rescue SocketError,
          Errno::ECONNREFUSED,
          Errno::ECONNRESET,
          Errno::ENETUNREACH,
          Timeout::Error,
          OpenURI::HTTPError => e
          # If authentication has been enabled, the server will return an HTTP
          # 403. This is "OK", since it means that the server is actually
          # ready to accept requests.
          return if e.message =~ /^403/
    
          Chef::Log.debug("Jenkins is not accepting requests - #{e.message}")
          sleep(0.5)
          retry
        end
      end
    rescue JenkinsTimeout
      raise JenkinsNotReady.new(endpoint, timeout)
    end
    

    This code repeatedly tries to connect to Jenkins, until it either works or a timeout is reached. You should be able to adapt this to mongo (you could call the command and check if it succeeds, or directly connect to the TCP port as the Jenkins code does.

  • A way in between would be to use Chef's retry parameter:

    execute "Add Mongo Users" do
      command "mongo #{host}:#{port} /tmp/mongo.setup.users.js"
      retry 10
      subscribes :run, 'service[mongod]', :delayed
    end
    

    I'm not entirely sure, if it will work, as the mongo command probably returns the failure pretty quickly, leaving little time up to the service to start (so combine with the all-mighty sleep?). Further, depending on the command that you execute, make sure that you won't cause negative side-effects (when it can connect to the service, but fails in a later step - and the result of this is that it runs once again. Think of data corruption and friends here).



来源:https://stackoverflow.com/questions/44365961/chef-mmake-sure-a-service-is-listennig-on-network

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!