Единорог, использующий исполняемый файл старого релиза (rbenv + runit)

Я сталкиваюсь с проблемой, которую легко исправить, но я не могу найти магию.

Unicorn использует runit и пытается указать на текущие выпуски Gemfile. В конце каждого развертывания единорогу отправляется сигнал USR2, и старый мастер успешно заменяется с использованием метода "развертывания с нулевым временем простоя". Какое-то время все было хорошо, пока я не дошел до того, что старые версии очищались. Тогда я понял, что runit указывает на каталог выпуска, который использовался при первом создании мастера единорога.

Я попытался добавить этот блок в unicorn.rb:

before_exec do |server|
    ENV['BUNDLE_GEMFILE'] = "/home/deploy/app/current/Gemfile"
end

Я также попытался обернуть пакет с этим сценарием:

#!/bin/bash

source /etc/profile.d/rbenv.sh

bundle $@

Я даже пытался установить переменную env BUNDLE_GEMFILE вручную, но, похоже, ничего из этого не работает.

Когда я смотрю на стандартный единорог после развертывания, я вижу это:

executing ["/home/deploy/app/releases/1279f2e2d88c90ba4e02eaba611a4ee6de6fee77/vendor/bundle/ruby/2.0.0/bin/unicorn", "-E", "staging", "-c", "/home/deploy/app/shared/config/unicorn.rb", "-D", {12=>#<Kgio::UNIXServer:fd 12>}] (in /home/deploy/app/releases/d6a582935d84cc0bec2e760c14d804a7c5e2146c)

Как вы можете видеть, команда выполняется в новом каталоге выпуска (d6a582935d84cc0bec2e760c14d804a7c5e2146c), но исполняемый файл unicron указывает на старый выпуск (1279f2e2d88c90ba4e02eaba611a4ee6de6fee77).

Если я вручную останавливаю / запускаю единорога, то используется правильная разблокировка, но это будет означать отсутствие "развертывания с нулевым временем простоя".

Я не уверен, в чем проблема, но я думаю, что это как-то связано с путями rbenv. У кого-нибудь есть предложения, как заставить единорога указывать на правильный (текущий) выпуск?

Я использую application_ruby LWRP с Chef для развертывания, если кто-то знаком. Это в основном только подражает Capistrano.

Соответствующие конфиги:

unicorn.rb:

current_path = '/home/deploy/app/current'

working_directory '/home/deploy/app/current'

worker_processes 8

listen "/home/deploy/app/shared/sockets/cms.sock"

timeout 60

pid '/home/deploy/app/shared/pids/unicorn.pid'

stderr_path '/home/deploy/app/shared/log/unicorn/unicorn.stderr.log'
stdout_path '/home/deploy/app/shared/log/unicorn/unicorn.stderr.log'

preload_app true

# Enable Copy on Write Garbage Collector - http://www.rubyenterpriseedition.com/faq.html#adapt_apps_for_cow
if GC.respond_to?(:copy_on_write_friendly=)
  GC.copy_on_write_friendly = true
end

before_fork do |server, worker|
  if defined?(ActiveRecord::Base)
    ActiveRecord::Base.connection.disconnect!
  end

  old_pid = "/home/deploy/app/shared/pids/unicorn.pid.oldbin"

  if File.exists?(old_pid) && server.pid != old_pid
    begin
      sig = (worker.nr + 1) >= server.worker_processes ? :TERM : :TTOU
      Process.kill(sig, File.read(old_pid).to_i)
    rescue Errno::ENOENT, Errno::ESRCH
      # someone else did our job for us
    end
  end
  # sleep 0 for small app, sleep 2 for big (300mb+)
  sleep 1
end

before_exec do |server|
  ENV['BUNDLE_GEMFILE'] = "#{current_path}/Gemfile"
end

after_fork do |server, worker|
  if defined?(ActiveRecord::Base)
    ActiveRecord::Base.establish_connection
  end
end

Runit скрипт единорога:

#!/bin/bash

if [ -d "/home/deploy/app/current" ] ; then

    function is_unicorn_alive {
        set +e
        if [ -n $1 ] && kill -0 $1 >/dev/null 2>&1; then
            echo "yes"
        fi
        set -e
     }

    echo "Service PID: $$"

    CUR_PID_FILE="/home/deploy/app/shared/pids/unicorn.pid"
    OLD_PID_FILE=$CUR_PID_FILE.oldbin

    if [ -e $OLD_PID_FILE ]; then
        OLD_PID=$(cat $OLD_PID_FILE)
        echo "Waiting for existing master ($OLD_PID) to exit"
        while [ -n "$(is_unicorn_alive $OLD_PID)" ]; do
            /bin/echo -n '.'
            sleep 2
        done
    fi

    if [ -e $CUR_PID_FILE ]; then
        CUR_PID=$(cat $CUR_PID_FILE)
        if [ -n "$(is_unicorn_alive $CUR_PID)" ]; then
            echo "Unicorn master already running. PID: $CUR_PID"
            RUNNING=true
        fi
    fi

    if [ ! $RUNNING ]; then
        echo "Starting unicorn"
        cd /home/deploy/app/current
        chown deploy:deploy /home/deploy/app/shared/pids/

        chpst -u deploy \
        /opt/rbenv/shims/bundle exec \
        unicorn \
        -E staging -c /home/deploy/app/shared/config/unicorn.rb -D

        sleep 3
        CUR_PID=$(cat $CUR_PID_FILE)
    fi

    function restart {
        echo "Initialize new master with USR2"
        kill -USR2 $CUR_PID
        # Make runit restart to pick up new unicorn pid
        sleep 2
        echo "Restarting service to capture new pid"
        exit
    }

    function graceful_shutdown {
        echo "Initializing graceful shutdown"
        kill -QUIT $CUR_PID
    }

    function unicorn_interrupted {
        echo "Unicorn process interrupted. Possibly a runit thing?"
    }

    trap restart HUP QUIT USR2 INT
    trap graceful_shutdown TERM KILL
    trap unicorn_interrupted ALRM

    echo "Waiting for current master to die. PID: ($CUR_PID)"
    while [ -n "$(is_unicorn_alive $CUR_PID)" ]; do
        /bin/echo -n '.'
        sleep 2
    done
else
    sleep 1
fi

1 ответ

Нашел это!

Добавил это в unicorn.rb:

Unicorn:: HttpServer:: START_CTX [0] = "# {current_path} / bin / unicorn"

Другие вопросы по тегам