使用Upstart管理Unicorn w / rbenv + bundler binstubs w / ruby -local-exec shebang

Modified on: Tue, 17 Sep 2019 13:40:02 +0800

好吧,这正在融化我的大脑。这可能与我不理解Upstart以及我应该理解的事实有关。对不起,很抱歉。

我正在尝试使用Upstart来管理Rails应用程序的Unicorn主进程。这是我当前的/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。所有这些事情的各种组合可能导致startstop挂起,然后Upstart对工作状态感到困惑。然后我必须重新启动机器来修复它。

我认为Upstart在检测何时/如果Unicorn正在分叉时遇到问题,因为我在我的ruby-local-exec脚本。这是:

#!/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的能力跟踪所有这些废话。

我正在尝试做什么?根据我的理解,Upstart中的expect节只能告诉(通过daemonfork),最多只能有两个分叉。 / p>

最佳答案

事实上,新贵的一个限制是它无法跟踪那些做独角兽正在做什么的守护进程......那就是fork / exec并退出他们的主进程。信不信由你,sshd在SIGHUP上做同样的事情,如果你看,/ etc / init / ssh.conf确保sshd在前台运行。这也是apache2仍然使用init.d脚本的一个原因。

当通过分叉然后退出接收SIGUSR1时,听起来像枪炮实际上是一种守护神。对于任何试图让流程保持活跃的流程经理来说,这会让人感到困惑。

我认为你有两种选择。 1只是在你需要时不使用SIGUSR1并停止/启动gunicorn。

另一种选择是不使用upstart的pid跟踪,只需这样做:

start on ..
stop on ..

pre-start exec gunicorn -D --pid-file=/run/gunicorn.pid
post-stop exec kill `cat /run/gunicorn.pid`

不像pid跟踪那样性感,但至少你不必写一个完整的init.d脚本。

(顺便说一句,这与shebangs / execs无关。这两件事就像运行常规可执行文件一样,所以它们不会产生任何额外的分支。)

作者:SpamapS

相关问答

添加新评论