我正在尝试使用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不是独角兽大师,而是一个sh过程.这本身并不是那么糟糕 – 如果我没有使用自动化Unicorn零停机时间部署策略.因为在我将-USR2发送给我的独角兽大师之后不久,一个新的主人产生了,旧的主人死了…… sh过程也是如此.所以Upstart认为我的工作已经死了,我不能再重新启动它,或者如果我想要停止它就停止它.
我玩过配置文件,试图将-D添加到Unicorn线(如:$APP_ROOT / bin / unicorn -c $APP_ROOT / config / unicorn.rb -E production -D)来守护Unicorn,我添加了expect守护程序行,但这也没有用.我也试过期待fork.所有这些事情的各种组合可能导致开始和停止挂起,然后Upstart对工作状态感到困惑.然后我必须重新启动机器来修复它.
我认为Upstart在检测何时/如果Unicorn正在分叉时遇到问题,因为我在我的$APP_ROOT / bin / unicorn脚本中使用了rbenv ruby-local-exec shebang.这里是:
#!/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 "$@"
所以那里有一位我担心的高管.它启动了一个Ruby进程,它启动了Unicorn,它可能会或可能不会自我守护,这一切都是从一个sh进程发生的……这让我严重怀疑Upstart跟踪所有这些废话的能力.
我甚至想做什么?根据我的理解,Upstart中的期望节只能被告知(通过守护进程或分叉)最多可以预期两个分叉.
解决方法
当通过分叉然后退出接收SIGUSR1时,听起来像gunicorn实际上是守护自己.对于任何试图保持流程存活的流程管理者来说,这会让人感到困惑.
我想你有两个选择. 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无关.这两件事就像运行常规可执行文件一样,因此它们不会产生任何额外的分支).