A coworker is getting different results for cap -vT unicorn compared to me, for the same version of capistrano, and the same Rails app:
app_name coworker$ cap -vT unicorn
cap unicorn:add_worker # Add a new worker
cap unicorn:duplicate # Duplicate Unicorn
cap unicorn:reload # Reload Unicorn
cap unicorn:remove_worker # Remove amount of workers
cap unicorn:restart # Restart Unicorn
cap unicorn:show_vars # Debug Unicorn variables
cap unicorn:shutdown # Immediately shutdown Unicorn
cap unicorn:start # Start Unicorn master process
cap unicorn:stop # Stop Unicorn
me:
app_name agrimm$ cap -vT unicorn
cap unicorn:graceful_stop # Unicorn graceful shutdown
cap unicorn:reload # Reload Unicorn
cap unicorn:start # Start Unicorn
cap unicorn:stop # Stop Unicorn
Extended help may be available for these tasks.
Type `cap -e taskname' to view it.
config/deploy.rb has require 'capistrano-unicorn'
My suspicion is that I'm not getting the tasks from capistrano unicorn, but what's going wrong? How do I diagnose the problem?
Related
I have two resque commands that I'd like to implement into capistrano so I can run it successfully on the server. I've checked by running these manually that they both work, however if I'm to keep these continuously running I'll end up with a broken pipe.
I'd like to be able to start resque:
queue=* rake environment resque:work
and start resque-scheduler:
rake environment resque:scheduler
anybody know how I can implement this into my deploy.rb file?
Try the capistrano-resque gem which should do exactly this (it includes support for resque-scheduler).
After setting it up, you'll get these Capistrano tasks:
➔ cap -vT | grep resque
cap resque:status # Check workers status
cap resque:start # Start Resque workers
cap resque:stop # Quit running Resque workers
cap resque:restart # Restart running Resque workers
cap resque:scheduler:restart #
cap resque:scheduler:start # Starts Resque Scheduler with default configs
cap resque:scheduler:stop # Stops Resque Schedule
(I currently help maintain this gem, so if you have any trouble with it just file an issue and I'll take a look).
I'm using Puma as application server for my Rails 4 project on MRI 2.1.0. I'm using Capistrano 3 to handle deployments. Everything is working like a charm. But, I recently noticed an issue with my deployment process. If I change my Gemfile then, puma fails to complete phased-restart and eventually all workers get killed. I'm running Puma in cluster mode and preload_app! is set true.
Here is my Capistrano recipe to handle phased-restart.
desc "Restart the application (phased restart)"
task :phased_restart do
on roles(:app) do |h|
execute "cd #{fetch(:current_path)} && bundle exec pumactl -S #{fetch(:puma_state)} phased-restart", :pty => true
end
end
This is truncated output of Capistrano log.
DEBUG [4790766f] Command: cd /home/app/current && bundle exec pumactl -S /home/app/shared/tmp/pids/puma.state phased-restart
DEBUG [de00176a] Command phased-restart sent success
INFO [de00176a] Finished in 0.909 seconds with exit status 0 (successful).
This is my config/puma.rb file.
#!/usr/bin/env puma
require 'active_support'
environment 'production'
daemonize
pidfile '/home/app/shared/tmp/pids/puma.pid'
state_path '/home/app/shared/tmp/pids/puma.state'
stdout_redirect 'log/puma_stdout.log', 'log/puma_stderr.log'
threads 100, 100
bind 'tcp://0.0.0.0:9292'
bind 'unix:////home/app/shared/tmp/pids/puma.sock'
on_worker_boot do
ActiveSupport.on_load(:active_record) do
ActiveRecord::Base.connection.disconnect! rescue ActiveRecord::ConnectionNotEstablished
ActiveRecord::Base.establish_connection(YAML.load_file("#{Rails.root}/config/database.yml")[Rails.env])
end
end
workers 4
preload_app!
Does anybody see anything wrong in my puma config file?
So, currently I do bundle exec cap production deploy:start to start Puma when this happens. But, I want zero-downtime-deployment in every cases.
Can Puma keep using old worker processes in case new spawned processes couldn't be started?
Do you know that preload_app! conflicts with phased restarts?
Proof: https://github.com/puma/puma/blob/0ea7af5e2cc8fa192ec82934a4a47880bdb592f8/lib/puma/configuration.rb#L333-L335
I think first you need to decide which to use.
For doing a phased restart you need to enable the prune_bundler option and disable preload_app!
See https://github.com/puma/puma/blob/master/DEPLOYMENT.md#restarting
To do zero-downtime deploys with Capistrano, you can use the capistrano3-puma gem with the following options:
set :puma_preload_app, false
set :puma_prune_bundler, true
I've been using this gem for a while and just took the dive to try deploying an actual staging environment to my staging server, and I ran into issues. Unicorn starts with the command unicorn_rails and -E production despite all the settings being correct afaik.
I noticed in deploy.rb that my unicorn_bin variable was set as unicorn_rails. I took out this setting in my deploy.rb. However unicorn:duplicate still executes the unicorn_rails command, when the default should be unicorn.
My vars are all set to staging in the deploy/staging.rb, as outlined in the multistage setup wiki document, but I noticed -E is still getting set to production.
Relevent info:
Here's my output from my unicorn.log file after a deploy:
executing ["/var/www/apps/myapp/shared/bundle/ruby/2.0.0/bin/unicorn_rails", "-c", "/var/www/apps/bundio/current/config/unicorn.rb", "-E", "production", "-D", {12=>#<Kgio::UNIXServer:/tmp/bundio.socket>, 13=>#<Kgio::TCPServer:fd 13>}] (in /var/www/apps/bundio/current)
Here's the output from cap -T (defaults to staging)
# Environments
rails_env "staging"
unicorn_env "staging"
unicorn_rack_env "staging"
# Execution
unicorn_user nil
unicorn_bundle "/usr/local/rvm/gems/ruby-2.0.0-p247#global/bin/bundle"
unicorn_bin "unicorn"
unicorn_options ""
unicorn_restart_sleep_time 2
# Relative paths
app_subdir ""
unicorn_config_rel_path "config"
unicorn_config_filename "unicorn.rb"
unicorn_config_rel_file_path "config/unicorn.rb"
unicorn_config_stage_rel_file_path "config/unicorn/staging.rb"
# Absolute paths
app_path "/var/www/apps/myapp/current"
unicorn_pid "/var/www/apps/myapp/shared/pids/unicorn.myapp.pid"
bundle_gemfile "/var/www/apps/myapp/current/Gemfile"
unicorn_config_path "/var/www/apps/myapp/current/config"
unicorn_config_file_path "/var/www/apps/myapp/current/config/unicorn.rb"
unicorn_config_stage_file_path
-> "/var/www/apps/myapp/current/config/unicorn/staging.rb"
And another curiousity, the unicorn_rails -E flag should reference the rails environment, whereas the unicorn -E should reference the rack env -- the rack env should only get the values developement and deployment, but it gets set to production, which is a bit strange (see unicorn docs for settings of the RACK_ENV variable.
Any insight into this would be much appreciated. On my staging server, I've also set the RAILS_ENV to staging. I've set up the things for rails for another environment, like adding staging.rb in my environments folder, adding a staging section to database.yml, etc.
Important lines in lib/capistrano-unicorn/config.rb talking about unicorn_rack_env:
_cset(:unicorn_env) { fetch(:rails_env, 'production' ) }
_cset(:unicorn_rack_env) do
# Following recommendations from http://unicorn.bogomips.org/unicorn_1.html
fetch(:rails_env) == 'development' ? 'development' : 'deployment'
end
Thanks in advance.
Ok, after a long time not having the correct environment, I have discovered the issue!
Basically, my init scripts were running BEFORE my capistrano-unicorn bin was doing its thing.
So, make sure that your init.d or upstart scripts to manage Unicorn and its workers are taken into account when capistrano-unicorn is doing the unicorn restart / reload / duplication tasks.
I did not think to look at these scripts when I had to debug the stale pid file / already running / unable to listen on socket errors. But it makes sense, as upstart starts Unicorn when it is not running, and then capistrano-unicorn is also attempting to start Unicorn.
I have now combined these capistrano tasks and hooks with Monit and a Unicorn init script.
Capistrano tasks:
namespace :monit do
desc ' wait 20 seconds '
task :wait_20_seconds do
sleep 20
end
task :monitor_all, :roles => :app do
sudo "monit monitor all"
end
task :unmonitor_all, :roles => :app do
sudo "monit unmonitor all"
end
desc 'monitor unicorn in the monit rc file'
task :monitor_unicorn, :roles => :app do
sudo "monit monitor unicorn"
end
desc 'unmonitor unicorn in the monit rc file'
task :unmonitor_unicorn, :roles => :app do
sudo "monit unmonitor unicorn"
end
end
Capistrano hooks:
after 'deploy:restart', 'unicorn:duplicate' # app preloaded. check https://github.com/sosedoff/capistrano-unicorn section for zero downtime
before 'deploy', "monit:unmonitor_unicorn"
before 'deploy:migrations', "monit:unmonitor_unicorn"
after 'deploy', 'monit:wait_20_seconds'
after "deploy:migrations", "monit:wait_20_seconds"
after 'monit:wait_20_seconds', 'monit:monitor_unicorn'
I use Monit to monitor my unicorn process:
Within /etc/monit/monitrc:
check process unicorn
with pidfile /var/www/apps/my_app/shared/pids/mypid.pid
start program = "/usr/bin/sudo service unicorn start"
stop program = "/usr/bin/sudo service unicorn stop"
Within your init script, you will start the unicorn process with something like:
unicorn_rails -c /var/www/apps/my_app/current/config/unicorn.rb -E staging -D
Make sure the -E flag is set to the correct environment. The capistrano-unicorn gem has directives using :set within deploy.rb which allow you to specify the environment for that unicorn process.
The following cap commands are available now, but I am unable to start unicorn using unicorn:start.
cap -vT
cap bundle:install # Install the current Bundler environment.
cap deploy # Deploys your project.
cap deploy:assets:clean # Run the asset clean rake task.
cap deploy:assets:clean_expired # Clean up any assets that haven't been...
cap deploy:assets:precompile # Run the asset precompilation rake task.
cap deploy:assets:rollback # to shared/assets/manifest.yml, and fi...
cap deploy:assets:symlink # [internal] This task will set up a sy...
cap deploy:assets:update_asset_mtimes # [internal] Updates the mtimes for ass...
cap deploy:check # Test deployment dependencies.
cap deploy:cleanup # Clean up old releases.
cap deploy:cold # Deploys and starts a `cold' application.
cap deploy:create_symlink # Updates the symlink to the most recen...
cap deploy:finalize_update # [internal] Touches up the released code.
cap deploy:migrate # Run the migrate rake task.
cap deploy:migrations # Deploy and run pending migrations.
cap deploy:pending # Displays the commits since your last ...
cap deploy:pending:diff # Displays the `diff' since your last d...
cap deploy:restart # Blank task exists as a hook into whic...
cap deploy:rollback # Rolls back to a previous version and ...
cap deploy:rollback:cleanup # [internal] Removes the most recently ...
cap deploy:rollback:code # Rolls back to the previously deployed...
cap deploy:rollback:revision # [internal] Points the current symlink...
cap deploy:setup # Prepares one or more servers for depl...
cap deploy:start # Blank task exists as a hook into whic...
cap deploy:stop # Blank task exists as a hook into whic...
cap deploy:symlink # Deprecated API.
cap deploy:update # Copies your project and updates the s...
cap deploy:update_code # Copies your project to the remote ser...
cap deploy:upload # Copy files to the currently deployed ...
cap development # Set the target stage to `development'.
cap invoke # Invoke a single command on the remote...
cap multistage:ensure # [internal] Ensure that a stage has be...
cap multistage:prepare # Stub out the staging config files.
cap production # Set the target stage to `production'.
cap rvm:create_gemset # Create gemset
cap rvm:install_gem # Install a gem, 'cap rvm:install_gem G...
cap rvm:install_ruby # Install RVM ruby to the server, creat...
cap rvm:install_rvm # Install RVM of the given choice to th...
cap rvm:uninstall_gem # Uninstall a gem, 'cap rvm:uninstall_g...
cap shell # Begin an interactive Capistrano session.
cap staging # Set the target stage to `staging'.
Extended help may be available for these tasks.
Type `cap -e taskname' to view it.
Following gems are available
gem list --local | grep cap
capistrano (2.14.1)
capistrano-ext (1.2.1)
capistrano-unicorn (0.1.6)
rvm-capistrano (1.2.7)
It seems that you haven't required it in your deploy.rb.
require 'capistrano-unicorn'
I'm get a Capistrano recipe to work with Bundler and a Rails (3.0.3) app but having trouble with some basic functionality.
Following the Bundler docs for "Automatic deployment with Capistrano", I'm trying to get more info on a task but for some reason it "doesn't exist"...
$ cap -e bundle:install
The task `bundle:install' does not exist.
The Capistrano (2.5.19) gem is installed and I'm trying to execute that command from the root of my project on the client (not the server).
in fact cap -T doesn't show anything related to 'bundle' or 'install'
$ cap -T
cap deploy # Deploys your project.
cap deploy:check # Test deployment dependencies.
cap deploy:cleanup # Clean up old releases.
cap deploy:cold # Deploys and starts a `cold' application.
cap deploy:migrate # Run the migrate rake task.
cap deploy:migrations # Deploy and run pending migrations.
cap deploy:pending # Displays the commits since your last deploy.
cap deploy:pending:diff # Displays the `diff' since your last deploy.
cap deploy:restart # Restarts your application.
cap deploy:rollback # Rolls back to a previous version and restarts.
cap deploy:rollback:code # Rolls back to the previously deployed version.
cap deploy:setup # Prepares one or more servers for deployment.
cap deploy:start # Start the application servers.
cap deploy:stop # Stop the application servers.
cap deploy:symlink # Updates the symlink to the most recently deployed ...
cap deploy:update # Copies your project and updates the symlink.
cap deploy:update_code # Copies your project to the remote servers.
cap deploy:upload # Copy files to the currently deployed version.
cap deploy:web:disable # Present a maintenance page to visitors.
cap deploy:web:enable # Makes the application web-accessible again.
cap invoke # Invoke a single command on the remote servers.
cap shell # Begin an interactive Capistrano session.
What am I doing wrong?
Did you include the recipe in your deploy.rb file?
require "bundler/capistrano"