目前我的独角兽大师需要在每次部署前手动杀死

Currently my unicorn master needs to be killed manually before each deployment

我在我的 rails4 应用程序中使用 capistrano,每次我发布新版本时 (=> cap production deploy) 我需要杀死服务器上的独角兽大师,这样 capistrano 就可以在没有任何东西的情况下行走失败。

### How can I automate the process of killing the unicorn process? 

This is how my deploy.rb is looking like:

lock '3.4.0'

set :application, 'maalify'
set :repo_url, 'git@github.com:iNeedCode/Maalify.git'
set :deploy_to, '/opt/www/maalify'
set :user, 'root'
set :linked_dirs, %w{log tmp/pids tmp/cache tmp/sockets}


set :rbenv_ruby, '2.2.1'
set :rbenv_type, :user
set :rbenv_path, "~/.rbenv"
set :rbenv_prefix, "RBENV_ROOT=#{fetch(:rbenv_path)} RBENV_VERSION=#{fetch(:rbenv_ruby)} #{fetch(:rbenv_path)}/bin/rbenv exec"
set :rbenv_map_bins, %w(rake gem bundle ruby rails)
set :rbenv_roles, :all
set :linked_files, %w{config/database.yml .rbenv-vars} # create these files manually ones on the server



# Capristrano3 unicorn
set :unicorn_pid, "/opt/www/maalify/current/shared/tmp/pids/unicorn.pid"
set :unicorn_config_path, "/opt/www/maalify/current/config/unicorn.rb"

# Clean up all older releases
before :deploy, "unicorn:stop"
after "deploy:publishing", "unicorn:start"
after "deploy:restart", "deploy:cleanup"


namespace :deploy do
  after :restart, :clear_cache do
    on roles(:web), in: :groups, limit: 3, wait: 10 do
      execute :rake, 'cache:clear'
    end
  end

end

更新

这是Unicorn.rb

# set path to application
app_dir = "/opt/www/maalify"
shared_dir = "#{app_dir}/shared"
working_directory "#{app_dir}/current"

# Set unicorn options
worker_processes 1
preload_app true
timeout 30

# Set up socket location
listen "#{shared_dir}/tmp/sockets/unicorn.sock", :backlog => 64

# Logging
stderr_path "#{shared_dir}/log/unicorn.stderr.log"
stdout_path "#{shared_dir}/log/unicorn.stdout.log"

# Set master PID location
pid "#{shared_dir}/tmp/pids/unicorn.pid"

添加 before_fork 后,我仍然遇到与之前没有手动杀死独角兽时相同的错误:

/opt/www/maalify/shared/bundle/ruby/2.2.0/gems/unicorn-4.8.3/lib/unicorn/http_server.rb:206:in `pid=': Already running on PID:16268 (or pid=/opt/www/maalify/shared/tmp/pids/unicorn.pid is stale) (ArgumentError)
        from /opt/www/maalify/shared/bundle/ruby/2.2.0/gems/unicorn-4.8.3/lib/unicorn/http_server.rb:135:in `start'
        from /opt/www/maalify/shared/bundle/ruby/2.2.0/gems/unicorn-4.8.3/bin/unicorn:126:in `<top (required)>'
        from /opt/www/maalify/shared/bundle/ruby/2.2.0/bin/unicorn:23:in `load'
        from /opt/www/maalify/shared/bundle/ruby/2.2.0/bin/unicorn:23:in `<main>'

我在你的独角兽配置文件​​中注意到下一个指令:

preload_app true

这是来自 docs 的信息:

HUP - reloads config file and gracefully restart all workers. If the "preload_app" directive is false (the default), then workers will also pick up any application code changes when restarted. If "preload_app" is true, then application code changes will have no effect; USR2 + QUIT (see below) must be used to load newer code in this case.

您可以将指令 preload_app 设置为 false,然后如果您需要重新加载代码,请向主进程发送 HUP 信号。

但这是另一种无需停机即可重新加载代码的方法。您需要在配置中实现 USR2 + QUIT 方法。这意味着当您发送 USR2 信号时,独角兽会启动新的应用程序实例而不会杀死旧实例。您可以挂钩 before_fork 回调,它将为您轻松杀死旧实例。

这是示例,将其添加到独角兽配置中:

before_fork do |server, worker|
  ActiveRecord::Base.connection.disconnect!

  old_pid = "#{server.config[:pid]}.oldbin"
  if File.exists?(old_pid) && server.pid != old_pid
    begin
      Process.kill("QUIT", File.read(old_pid).to_i)
    rescue Errno::ENOENT, Errno::ESRCH
      # someone else did our job for us
    end
  end
end

after_fork do |server, worker|
  ActiveRecord::Base.establish_connection
end

现在发送 USR2 信号给 master 进程并检查它!

下一步是改变您的 deploy.rb。您需要删除所有 unicorn 个挂钩并添加下一个:

after 'deploy:publishing', 'deploy:restart'
namespace :deploy do
  task :restart do
    invoke 'unicorn:legacy_restart'
  end
end

最后一步:修复 deploy.rb.

中的 pid 路径
set :unicorn_pid, "/opt/www/maalify**/current/shared/**tmp/pids/unicorn.pid"

必须是:

set :unicorn_pid, "/opt/www/maalify/shared/tmp/pids/unicorn.pid"