12

当我cap production deploy使用 Capistrano 3.0.1 时,我正在尝试启动或重新启动 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

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

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

# 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

我也尝试将运行放在 :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    

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

unicorn -c /etc/unicorn/deployrails.conf.rb -D我可以从我的 ssh'd VM shell启动独角兽进程。

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

$ kill USR2 58798
bash: kill: USR2: arguments must be process or job IDs

总的来说,我对 Ruby、Rails 和 Deployment 很陌生。我有一个带有 Ubuntu、Nginx、RVM 和 Unicorn 的 VirtualBox 设置,到目前为止我很兴奋,但是这个真的让我很困惑,任何建议或见解都值得赞赏。

4

5 回答 5

14

我正在使用以下代码:

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
于 2014-01-21T18:57:23.510 回答
6

不能说有关 capistrano 3(我使用 2)的任何具体内容,但我认为这可能会有所帮助:如何在 Capistrano v3 的服务器上运行 shell 命令?. 我也可以分享一些与独角兽相关的经验,希望对您有所帮助。

我假设您想要 24/7 正常重启方法。

让我们就此事查阅unicorn 文档。对于优雅重启(没有停机时间),您可以使用两种策略:

  1. kill -HUP unicorn_master_pid它要求您的应用禁用“preload_app”指令,从而增加每个独角兽工人的启动时间。如果你能忍受 - 继续,这是你的决定。

  2. kill -USR2 unicorn_master_pid kill -QUIT unicorn_master_pid

更复杂的方法,当您已经在处理性能问题时。基本上它会重新执行独角兽主进程,然后你应该杀死它的前任。理论上你可以处理 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或init 监督之下。这样,您的 capistrano 任务将像或sv reload unicorn一样简单。这是好事。restart unicorn/etc/init.d/unicorn restart

于 2013-11-11T00:27:34.870 回答
4

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

但是,我对 gem(以及任何不使用 init.d 脚本的方法)的问题是,您现在可能有两种方法来管理您的独角兽进程。一个带有这个 cap 任务,一个带有 init.d 脚本。Monit / God 之类的东西会感到困惑,您可能会花费数小时调试为什么要尝试启动两个独角兽进程,然后您可能会开始讨厌生活。

目前我在 capistrano 3 和 unicorn 中使用以下内容:

  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,老主人在消失之前徘徊了几秒钟。

于 2014-02-28T15:57:46.897 回答
1

要查看所有大写字母:

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

于 2020-09-18T13:00:10.587 回答
0

您可以尝试使用此处所写的本地 capistrano 方式:

如果 preload_app:true 并且您需要 capistrano 来清理您的 oldbin pid,请使用:

after 'deploy:publishing', 'deploy:restart'
namespace :deploy do
  task :restart do
    invoke 'unicorn:legacy_restart'
  end
end
于 2015-11-30T15:05:56.693 回答