Unicorn没有通过新部署的Rails应用程序(Capistrano,Nginx)获取更改

时间:2016-06-09 23:46:32

标签: ruby-on-rails-4 deployment capistrano unicorn

我刚接触部署,所以这可能是一个新手的错误,但现在就是这样。

我有一个Rails 4应用程序,我使用Capistrano,Unicorn和Nginx的组合部署到Linux服务器。部署脚本运行正常,应用程序现在可以在所需的IP上访问,因此非常棒。问题是,a)Unicorn在部署时没有重新启动(至少,PID不会改变)和b)毫不奇怪,新的变化并没有反映在可用的应用程序中。除了完全停止并重新启动独角兽以便刷新它之外,我似乎无能为力。如果我这样做,那么就会发现变化,但这个过程显然不理想。

手动,如果我运行kill -s HUP $UNICORN_PID那么工人的工具会改变而不是工作人员的工资,并且不会改变(显然他们应该是这样);使用USR2似乎对当前进程没有影响。

这是我使用的独角兽初始化脚本,基于其他类似问题的堆栈溢出问题的建议:

set -e

USAGE="Usage: $0 <start|stop|restart|upgrade|rotate|force-stop>"

# app settings
USER="deploy"
APP_NAME="app_name"
APP_ROOT="/path/to/$APP_NAME"
ENV="production"

# environment settings
PATH="/home/$USER/.rbenv/shims:/home/$USER/.rbenv/bin:$PATH"
CMD="cd $APP_ROOT/current && bundle exec unicorn -c config/unicorn.rb -E $ENV -D"
PID="$APP_ROOT/shared/pids/unicorn.pid"
OLD_PID="$PID.oldbin"
TIMEOUT=${TIMEOUT-60}

# make sure the app exists
cd $APP_ROOT || exit 1

sig () {
  test -s "$PID" && kill -$1 `cat $PID`
}

oldsig () {
  test -s $OLD_PID && kill -$1 `cat $OLD_PID`
}

case $1 in
  start)
    sig 0 && echo >&2 "Already running" && exit 0
    echo "Starting $APP_NAME"
    su - $USER -c "$CMD"
    ;;
  stop)
    echo "Stopping $APP_NAME"
    sig QUIT && exit 0
    echo >&2 "Not running"
    ;;
  force-stop)
    echo "Force stopping $APP_NAME"
    sig TERM && exit 0
    echo >&2 "Not running"
    ;;
  restart|reload)
    sig HUP && echo "reloaded $APP_NAME" && exit 0
    echo >&2 "Couldn't reload, starting '$CMD' instead"
    run "$CMD"
    ;;
  upgrade)
    if sig USR2 && sleep 2 && sig 0 && oldsig QUIT
    then
      n=$TIMEOUT
      while test -s $OLD_PID && test $n -ge 0
      do
        printf '.' && sleep 1 && n=$(( $n - 1 ))
      done
      echo

    if test $n -lt 0 && test -s $OLD_PID
    then
      echo >&2 "$OLD_PID still exists after $TIMEOUT seconds"
      exit 1
    fi
    exit 0
  fi
  echo >&2 "Couldn't upgrade, starting '$CMD' instead"
  su - $USER -c "$CMD"
  ;;
  rotate)
    sig USR1 && echo rotated logs OK && exit 0
    echo >&2 "Couldn't rotate logs" && exit 1
    ;;
  *)
    echo >&2 $USAGE
    exit 1
    ;;
esac

使用此脚本,startstop按预期工作,但reload / restart不执行任何操作(他们打印预期输出但不会更改正在运行的pids)和upgrade失败。根据错误日志,它是因为第一个主服务器仍在运行(ArgumentError: Already running on PID: $PID)。

这是我的独角兽.rb:

app_path = File.expand_path("../..", __FILE__)
working_directory "#{app_path}"
pid               "#{app_path}/../../shared/pids/unicorn.pid"

# listen
listen "#{app_path}/../../shared/sockets/unicorn.sock", :backlog => 64

# logging
stderr_path "#{app_path}/../../shared/log/unicorn.stderr.log"
stdout_path "#{app_path}/../../shared/log/unicorn.stdout.log"

# workers
worker_processes 3

# use correct Gemfile on restarts
before_exec do |server|
  ENV['BUNDLE_GEMFILE'] = "#{working_directory}/Gemfile"
end

# preload
preload_app false

before_fork do |server, worker|
  old_pid = "#{app_path}/shared/pids/unicorn.pid.oldbin"
  if File.exists?(old_pid) && server.pid != old_pid
    begin
      Process.kill("QUIT", File.read(old_pid).to_i)
    rescue Errno::ENOENT, Errno::ESRCH
      # someone else did our job for us
    end
  end
end

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

非常感谢任何帮助,谢谢!

2 个答案:

答案 0 :(得分:1)

很难说是肯定的,因为我之前没有遇到过这个问题,但我的预感是这是你的问题:

app_path = File.expand_path("../..", __FILE__)
working_directory "#{app_path}"

每次部署时,Capistrano都会在releases/<timestamp>位置为您的应用创建新目录。然后它会更新current符号链接以指向此最新版本目录。

在您的情况下,您可能会错误地告诉Unicorn使用releases/<timestamp>作为其working_directory。 (SSH到服务器并检查unicorn.rb的内容是否确定。)相反,您应该做的是指向current。这样你就不必停下来冷启动独角兽让它看到新的工作目录。

# Since "current" is a symlink to the current release,
# Unicorn will always see the latest code.
working_directory "/var/www/my-app/current"

我建议重写你的unicorn.rb,这样你就不会使用相对路径了。而是将绝对路径硬编码为currentshared。可以这样做,因为每个版本的路径都保持不变。

答案 1 :(得分:0)

该行

ENV="production"

对我来说非常可疑。我怀疑它想成为

RAILS_ENV="production".

没有这个不知道的轨道醒来不知道它是哪个环境?