使用Capistrano 3.x启动或重启Unicorn

时间:2013-11-10 23:56:49

标签: ruby nginx unicorn capistrano3

我在使用Capistrano 3.0.1 cap production deploy时尝试启动或重启Unicorn。我有一些例子,我使用Capistrano 2.x使用类似的东西:

namespace :unicorn do
  desc "Start unicorn for this application"
  task :start do
    run "cd #{current_path} && bundle exec unicorn -c /etc/unicorn/myapp.conf.rb -D"
  end
end

但是当我尝试在Capistrano 3.x的run中使用deploy.rb时,我得到一个未定义的方法错误。

以下是我尝试过的几件事:

# within the :deploy I created a task that I called after :finished
namespace :deploy do
...

  task :unicorn do
    run "cd #{current_path} && bundle exec unicorn -c /etc/unicorn/myapp.conf.rb -D"
  end

  after :finished, 'deploy:unicorn'

end

我也尝试将run放在:restart任务

namespace :deploy do
  desc 'Restart application'
  task :restart do

  on roles(:app), in: :sequence, wait: 5 do
    # Your restart mechanism here, for example:
    # execute :touch, release_path.join('tmp/restart.txt')
    execute :run, "cd #{current_path} && bundle exec unicorn -c /etc/unicorn/deployrails.conf.rb -D"
  end
end    

如果我在本地shell中只使用run "cd ... " then I'll get a个错误数量的参数(1表示0)`。

我可以从我的ssh&#VM VM shell中使用unicorn -c /etc/unicorn/deployrails.conf.rb -D启动独角兽进程。

我可以使用kill USR2从VM shell中杀死主Unicorn进程,但即使进程被终止,我也会收到错误。然后,我可以使用unicorn -c ...

重新开始此过程
$ kill USR2 58798
bash: kill: USR2: arguments must be process or job IDs

我对Ruby,Rails和部署一般都很陌生。我有一个使用Ubuntu,Nginx,RVM和Unicorn的VirtualBox设置,到目前为止我非常兴奋,但是这个真的很烦我,任何建议或见解都值得赞赏。

5 个答案:

答案 0 :(得分:13)

我正在使用以下代码:

namespace :unicorn do
  desc 'Stop Unicorn'
  task :stop do
    on roles(:app) do
      if test("[ -f #{fetch(:unicorn_pid)} ]")
        execute :kill, capture(:cat, fetch(:unicorn_pid))
      end
    end
  end

  desc 'Start Unicorn'
  task :start do
    on roles(:app) do
      within current_path do
        with rails_env: fetch(:rails_env) do
          execute :bundle, "exec unicorn -c #{fetch(:unicorn_config)} -D"
        end
      end
    end
  end

  desc 'Reload Unicorn without killing master process'
  task :reload do
    on roles(:app) do
      if test("[ -f #{fetch(:unicorn_pid)} ]")
        execute :kill, '-s USR2', capture(:cat, fetch(:unicorn_pid))
      else
        error 'Unicorn process not running'
      end
    end
  end

  desc 'Restart Unicorn'
  task :restart
  before :restart, :stop
  before :restart, :start
end

答案 1 :(得分:6)

不能说有关capistrano 3的任何具体内容(我使用2),但我认为这可能有所帮助:How to run shell commands on server in Capistrano v3?。 此外,我可以分享一些与独角兽相关的经历,希望这会有所帮助。

我假设你想要24/7优雅的重启方法。

让我们就此问题咨询unicorn documentation。为了优雅重启(无停机时间),您可以使用两种策略:

  1. kill -HUP unicorn_master_pid它要求您的应用禁用'preload_app'指令,增加每个独角兽工作人员的开始时间。如果你可以忍受 - 继续,这是你的电话。

  2. kill -USR2 unicorn_master_pid kill -QUIT unicorn_master_pid

  3. 当您处理性能问题时,更复杂的方法。基本上它会重新执行独角兽主进程,那么你应该杀掉它的前身。从理论上讲,你可以处理usr2-sleep-quit方法。另一个(也是正确的,我可能会说)方式是使用unicorn before_fork钩子,它将被执行,当新的主进程将被生成并将尝试为自己的新子进程。 你可以在config / unicorn.rb中输入这样的东西:

    # Where to drop a pidfile
    pid project_home + '/tmp/pids/unicorn.pid'
    
    before_fork do |server, worker|
      server.logger.info("worker=#{worker.nr} spawning in #{Dir.pwd}")
    
      # graceful shutdown.
      old_pid_file = project_home + '/tmp/pids/unicorn.pid.oldbin'
      if File.exists?(old_pid_file) && server.pid != old_pid_file
        begin
          old_pid = File.read(old_pid_file).to_i
          server.logger.info("sending QUIT to #{old_pid}")
          # we're killing old unicorn master right there
          Process.kill("QUIT", old_pid)
        rescue Errno::ENOENT, Errno::ESRCH
          # someone else did our job for us
        end
      end
    end
    

    当新的独角兽准备分叉工人时,杀死旧独角兽或多或少是安全的。你不会那样得到任何停机时间,老独角兽会等待它的工人完成。

    还有一件事 - 您可能希望将其置于runit或初始监督之下。这样,您的capistrano任务就像sv reload unicornrestart unicorn/etc/init.d/unicorn restart一样简单。这是好事。

答案 2 :(得分:4)

我要把它扔进戒指:capistrano 3 unicorn gem

但是,我对gem的问题(以及任何不使用init.d脚本的方法)是,您现在可以使用两种方法来管理您的独角兽进程。一个有这个cap任务,一个有init.d脚本。像Monit / God这样的事情会让人感到困惑,你可能会花几个小时调试为什么你有两个独角兽进程试图开始,然后你可能会开始讨厌生活。

目前我在capistrano 3和独角兽中使用以下内容:

  namespace :unicorn do
  desc 'Restart application'
    task :restart do
      on roles(:app) do
        puts "restarting unicorn..."
        execute "sudo /etc/init.d/unicorn_#{fetch(:application)} restart"
        sleep 5
        puts "whats running now, eh unicorn?"
        execute "ps aux | grep unicorn"
      end
    end
end

以上内容与preload_app:true以及@dredozubov提到的before_fork和after_fork语句相结合

注意我已将init.d / unicorn脚本命名为unicorn_application_name。

启动的新工人应该杀掉旧工人。您可以看到ps aux | grep unicorn旧主人在它消失之前会挂起几秒钟。

答案 3 :(得分:0)

您可以尝试使用原始的capistrano方式编写here

如果preload_app:true,你需要使用capistrano清理你的oldbin pid:

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

答案 4 :(得分:0)

要查看所有大写字母:

cap -T

它显示:

***
cap unicorn:add_worker             # Add a worker (TTIN)
cap unicorn:duplicate              # Duplicate Unicorn; alias of unicorn:re...
cap unicorn:legacy_restart         # Legacy Restart (USR2 + QUIT); use this...
cap unicorn:reload                 # Reload Unicorn (HUP); use this when pr...
cap unicorn:remove_worker          # Remove a worker (TTOU)
cap unicorn:restart                # Restart Unicorn (USR2); use this when ...
cap unicorn:start                  # Start Unicorn
cap unicorn:stop                   # Stop Unicorn (QUIT)
***

因此,要开始生产独角兽:

cap production unicorn:start

然后重新启动:

cap production unicorn:restart 

PS不要忘记正确使用 gem capistrano3-unicorn

https://github.com/tablexi/capistrano3-unicorn