Запуск или перезапуск Unicorn с помощью Capistrano 3.икс

Я пытаюсь запустить или перезапустить Unicorn, когда я делаю cap production deploy С Capistrano 3.0.1. У меня есть несколько примеров, которые я получил, работая с Capistrano 2.х, используя что-то вроде:

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

но когда я пытаюсь использовать run на deploy.rb для 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 task

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неправильное количество аргументов (1 Для 0) ' в локальной оболочке.

я могу начать процесс единорога с unicorn -c /etc/unicorn/deployrails.conf.rb -D из моей оболочки ssh'D VM.

я могу убить процесс master Unicorn из оболочки VM, используя kill USR2, но даже если процесс убит, я получаю ошибку. Затем я могу начать процесс снова, используя unicorn -c ...

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

Я очень новичок в Ruby, Rails и развертывании в целом. У меня есть настройка VirtualBox с Ubuntu, Nginx, RVM и Unicorn, Я очень взволнован до сих пор, но это действительно возится со мной, любой совет или понимание ценятся.

4 ответов


Не могу сказать ничего конкретного о capistrano 3(я использую 2), но я думаю, что это может помочь:как запустить команды оболочки на сервере в Capistrano v3?. Также я могу поделиться опытом, связанным с единорогом, надеюсь, это поможет.

Я предполагаю, что вы хотите 24/7 перезапуска подход.

давайте советуйте единорог документации в этом отношении. Для изящного перезапуска (без простоя) вы можете использовать два стратегии:

  1. kill -HUP unicorn_master_pid для вашего приложения требуется отключить директиву "preload_app", увеличивая время запуска каждого из работников unicorn. Если вы можете жить с этим - продолжайте, это ваш выбор.

  2. kill -USR2 unicorn_master_pid kill -QUIT unicorn_master_pid

более сложный подход, когда вы уже имеете дело с проблемами производительности. В основном он будет вынужден освоить процесс единорог, то вы должны убить его предшественник. Теоретически вы можете иметь дело с подходом usr2-sleep-quit. Другой (и правильный, я могу сказать) способ-использовать unicorn перед крючком, он будет выполнен, когда новый мастер-процесс будет порожден и попытается для новых детей для себя. Вы можете поместить что-то подобное в 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

более или менее безопасно убить старого единорога, когда новый готов раскошелиться на рабочих. Вы не получите никакого времени простоя таким образом, и старый единорог будет ждать, пока это рабочие заканчивать.

и еще одно - вы можете поставить его под Рунит или надзор инициализации. Таким образом, ваши задачи capistrano будут такими же простыми, как sv reload unicorn, restart unicorn или /etc/init.d/unicorn restart. Это хорошо.


Я использую следующий код:

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

Я просто собираюсь бросить это в кольцо:capistrano 3 unicorn gem

однако, моя проблема с драгоценным камнем (и любой подход, не использующий init.D script), заключается в том, что теперь у вас могут быть два метода управления процессом unicorn. Один с этой задачей cap и один с init.D скрипты. Такие вещи, как Monit / God, будут запутаны, и вы можете потратить часы на отладку, почему у вас есть два процесса unicorn, пытающихся начать, а затем вы можете начать ненавидеть жизнь.

В настоящее время я использую следующее С 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 и заявлениями before_fork и after_fork, упомянутыми @dredozubov

Примечание я назвал свой init.D / Unicorn скрипт unicorn_application_name.

новый работник, который должен убить старого. Вы можете видеть с ps aux | grep unicorn что старого хозяина висит вокруг в течение нескольких секунд, прежде чем он исчезает.


вы можете попробовать использовать родной путь capistrano, как написано здесь:

Если preload_app: true и вам нужно capistrano для очистки вашего oldbin pid использовать:

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