Использование Upstart для управления Unicorn w/ rbenv + bundler binstubs w/ ruby-local-exec shebang

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

Я пытаюсь использовать Upstart для управления процессом Unicorn master в приложении Rails. Вот мой текущий /etc/init/app.conf:

description "app"

start on runlevel [2]
stop on runlevel [016]

console owner

# expect daemon

script
  APP_ROOT=/home/deploy/app
  PATH=/home/deploy/.rbenv/shims:/home/deploy/.rbenv/bin:$PATH
  $APP_ROOT/bin/unicorn -c $APP_ROOT/config/unicorn.rb -E production # >> /tmp/upstart.log 2>&1
end script

# respawn

Это работает просто отлично - единороги запускаются отлично. Что не очень хорошо, так это то, что обнаруженный PID принадлежит не мастеру Unicorn, а процессу sh. Само по себе это тоже не так уж плохо - если бы я не использовал автоматическую стратегию развертывания Unicorn с нулевым временем простоя. Потому что вскоре после того, как я отправил -USR2 моему мастеру Unicorn, появляется новый мастер, а старый умирает... и процесс sh тоже. Поэтому Upstart думает, что моя работа умерла, и я больше не могу перезапустить ее с помощью restart или остановить с помощью stop, если захочу.

Я поиграл с конфигурационным файлом, пытаясь добавить -D к строке Unicorn (вот так: $APP_ROOT/bin/unicorn -c $APP_ROOT/config/unicorn.rb -E production -D) для демонизации Unicorn, и я добавил строку expect daemon, но это тоже не сработало. Я также пробовал expect fork. Различные комбинации всех этих вещей могут привести к зависанию start и stop, и тогда Upstart запутается в состоянии задания. Затем мне приходится перезагружать машину, чтобы исправить ситуацию.

Я думаю, что у Upstart проблемы с определением того, когда/если Unicorn форкается, потому что я использую rbenv + ruby-local-exec shebang в моем $APP_ROOT/bin/unicorn скрипте. Вот он:

#!/usr/bin/env ruby-local-exec
#
# This file was generated by Bundler.
#
# The application 'unicorn' is installed as part of a gem, and
# this file is here to facilitate running it.
#

require 'pathname'
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
  Pathname.new(__FILE__).realpath)

require 'rubygems'
require 'bundler/setup'

load Gem.bin_path('unicorn', 'unicorn')

Кроме того, сценарий ruby-local-exec выглядит так:

#!/usr/bin/env bash
#
# `ruby-local-exec` is a drop-in replacement for the standard Ruby
# shebang line:
#
#    #!/usr/bin/env ruby-local-exec
#
# Use it for scripts inside a project with an `.rbenv-version`
# file. When you run the scripts, they'll use the project-specified
# Ruby version, regardless of what directory they're run from. Useful
# for e.g. running project tasks in cron scripts without needing to
# `cd` into the project first.

set -e
export RBENV_DIR="${1%/*}"
exec ruby "$@"

Итак, там есть exec, который меня беспокоит. Он запускает процесс Ruby, который запускает Unicorn, который может или не может демонизировать себя, и все это происходит из процесса sh в первую очередь... что заставляет меня серьезно сомневаться в способности Upstart отслеживать всю эту ерунду.

Возможно ли вообще то, что я пытаюсь сделать? Насколько я понимаю, строфа expect в Upstart может быть указана (через daemon или fork) только для ожидания максимум двух форков.

9
задан codykrieger 29 December 2011 в 11:41
поделиться