TonyLovesDevOps
TonyLovesDevOps

Reputation: 91

How can I make capistrano wait for a service to start up on all servers before continuing?

We do our deployments with capistrano. Our website consists of a rails frontend and java API backend.

I have a situation where the java API application takes about 15 minutes to start up and the rails application can't run without it. Initially I tried to loop within capistrano using the capture command to wait until the application started listening on the port (8080 in our case):

desc "Start api"
task :api, :roles => :api do
  run("cd #{home_api} && ./api.sh start > /dev/null 2>&1 &")
  sleep 1
  api_status = nil
  until api_status
    api_status = capture("echo `netstat -tln | grep 8080`")
    sleep 60
  end
  puts "API Started successfully."
end

However, capture only runs on one server (we have several API machines) and if that one finishes starting up before the others the deployment may proceed before all the API machines are ready.

I need something that will wait for a port to be open on all servers matching the specified role before moving on.

Upvotes: 4

Views: 3995

Answers (1)

TonyLovesDevOps
TonyLovesDevOps

Reputation: 91

Here's how I am currently doing this:

Using 'run' to execute some shell commands that won't return until the port is open (or until 30 minutes have passed in this case.) This will run on all the matching servers and won't continue until all of them have completed.

desc "Start api"
task :api, :roles => :api do
  run("cd #{home_api} && ./api.sh start > /dev/null 2>&1 &")
  sleep 1
  run("for i in {0..60}; do echo \"Waiting for API to start\"; if [[ \"\" != \"$\(netstat -an |grep 8080\)\" ]]; then break; fi; sleep 30; done")
end

I'm curious to see how other people are doing this, there surely is a better way?

Upvotes: 4

Related Questions