问题描述
我是新进行部署,所以这可能是一个新秀的错误,但是在这里。
I'm new to deploying, so this is probably a rookie mistake, but here it goes.
我有一个Rails 4应用程序,我正在部署一个使用Capistrano,Unicorn和Nginx组合的Linux服务器。部署脚本运行正常,应用程序现在可以达到所需的IP,所以这是非常好的。事情是,a)Unicorn在部署时不重新启动(至少PID不改变),b)毫不奇怪,新的更改没有反映在可用的应用程序中。除了完全停止和重新启动独角兽之外,我似乎无法做任何改动。如果我这样做,那么这些更改是被接受的,但这个过程显然不是很理想。
I have a Rails 4 app that I'm deploying to a Linux server using a combination of Capistrano, Unicorn, and Nginx. The deploy script runs fine and the app is now reachable at the desired IP, so that's great. The thing is, a) Unicorn doesn't restart upon deployment (at least, the PIDs don't change) and b) not surprisingly, the new changes aren't reflected in the available app. I don't seem to be able to do anything other than completely stopping and restarting unicorn in order to refresh it. If I do this, then the changes are picked up, but this process is obviously not ideal.
手动,如果我运行 kill -s HUP $ UNICORN_PID
然后,工作人员的变化而不是主人,变化不会被拾起(显然它们应该是);使用 USR2
似乎对当前进程没有影响。
Manually, if I run kill -s HUP $UNICORN_PID
then the pids of the workers change but not the master, and changes aren't picked up (which, apparently they are supposed to be); using USR2
appears to have no effect on the current processes.
这是我使用的unicorn init脚本,基于来自其他堆栈溢出问题的相似问题的建议:
Here's the unicorn init script I'm using, based on suggestions from other stack overflow questions with similar problems:
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
使用此脚本,开始
和停止
按预期工作,但重新加载
/ 重新启动
不做任何事情(他们打印预期的输出,但不要更改运行的pids)和升级
失败。根据错误日志,这是因为第一个主程序仍在运行( ArgumentError:已经在PID上运行:$ PID
)。
Using this script, start
and stop
work as expected, but reload
/restart
do nothing (they print the expected output but don't change the running pids) and upgrade
fails. According to the error log, it's because the first master is still running (ArgumentError: Already running on PID: $PID
).
这是我的unicorn.rb:
And here's my unicorn.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
任何帮助都非常感谢,谢谢!
Any help is very much appreciated, thanks!
推荐答案
很难说一定,因为我以前没有遇到这个特定的问题,但我的预期是这是你的问题:
It is hard to say for certain, since I haven't encountered this particular issue before, but my hunch is that this is your problem:
app_path = File.expand_path("../..", __FILE__)
working_directory "#{app_path}"
每次部署时,Capistrano都会在 release /< timestamp>
位置为您的应用程序创建一个新目录。然后,它更新一个当前
符号链接指向此最新版本目录。
Every time you deploy, Capistrano creates a new directory for your app at the location releases/<timestamp>
. It then updates a current
symlink to point at this latest release directory.
在您的情况下,您可能会错误地告诉Unicorn使用 release /< timestamp>
作为其 working_directory
。 (SSH到服务器并检查 unicorn.rb
的内容是确定的。)而应该做的是指向当前
。这样你就不必停下来,冷静地开始独角兽,让它看到新的工作目录。
In your case, you may mistakenly be telling Unicorn to use releases/<timestamp>
as its working_directory
. (SSH to the server and check the contents of unicorn.rb
to be certain.) Instead, what you should do is point to current
. That way you don't have to stop and cold start unicorn to get it to see the new working directory.
# 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,以便您不使用相对路径。而是将绝对路径硬编码为当前
和共享
。可以这样做,因为每个版本的路径将保持不变。
I suggest rewriting your unicorn.rb so that you aren't using relative paths. Instead hard-code the absolute paths to current
and shared
. It is OK to do this because those paths will remain the same for every release.
这篇关于独角兽不会随着Rails应用程序(Capistrano,Nginx)的新部署而改变,的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!