部署 rails capistrano-passenger 重启应用失败的问题

flybee · 2018年10月20日 · 最后由 flybee 回复于 2019年04月16日 · 6047 次阅读

执行几次的部署之后(完成 5 次部署),就会部署失败,报错信息:Bundler::GemfileNotFound,报错语句:passenger-config restart-app /XXX/XXX/XXX --ignore-app-not-running

背景: 使用 passenger 作为 app server, capistrano 作部署工具 使用了 gem 'capistrano-passenger'完成 restart app 的任务,实际执行命令为:passenger-config restart-app /XXX/XXX/XXX --ignore-app-not-running

找的答案如下:https://stackoverflow.com/questions/15393462/what-can-i-do-about-a-bundlergemfilenotfound-error

“In my experience, this will occur when your code is not executing in the directory you think it is (hence the previous answer), or the directory containing the Gemfile has been moved or deleted.
I experienced this when I had been running unicorn on a server running an app that had been deployed with Capistrano. After cleaning up some old "releases" folders, I got this error when I tried to cap deploy a new release.
Because unicorn had been started with bundle exec, it was still using the Gemfile from the directory it was started in; sending the USR2 signal would tell it to reload the application, but it will still use the old Gemfile before loading the newly-deployed app. Of course, I had deleted that Gemfile when I deleted the old releases.
The solution was to restart unicorn with a new bundle exec in the new directory, to load the new Gemfile and then the new app.
So, the answer above is correct. You just need to figure out why the Gemfile you thought you were using is not being used.”

有人遇到这种情况吗?如何解决的?

已经解决

passenger 在启动的时候,默认使用 bundle 的执行环境,bundle 在执行的时候会查找 gemfile 文件,查找顺序为 ENV[BUNDLE_GEMFILE], ../Gemfile;

如果在首次启动 passenger 的时候,没有加载环境变量 BUNDLE_GEMFILE 的话,那么 gemfile 文件的位置就是应用的根目录下的 Gemfile 文件路径,一旦 passenger 启动完成,那么 bundle 使用的 gemfile 文件的路径就不会再更改了 (记录在 passenger 的进程中)

所以在使用 passenger-config restart 命令的时候,在经过几次 capistrano 的 keep_release 之后,最初始的那个版本被删除之后,重启会失败,报错 (Bundler::GemfileNotFound)

所以在启动 passenger 的时候,指定环境变量:BUNDLE_GEMFILE 即可,类似于如下:

BUNDLE_GEMFILE=/var/www/XXX/current/Gemfile bundle exec passenger start

包括 unicorn 的启动也是如此 只不过 unicorn 会在启动脚本里面加上:

before_exec do |server|
  ENV['BUNDLE_GEMFILE'] = "/var/www/XXX/current/Gemfile"

end

道理是一样的

在首次启动 passenger 的时候,需要明确 gemfile 的位置 下面是我写的启动脚本:

#!/bin/bash -l
# set -x

dir=/var/www/XXX/current
case $1 in
start)
    cd $dir && (BUNDLE_GEMFILE="${dir}/Gemfile" bundle exec passenger start)
    echo -e "\033[32mpassenger server start OK!\033[0m"
    ;;
stop)
    cd $dir && (BUNDLE_GEMFILE="${dir}/Gemfile" bundle exec passenger stop)
    echo -e "\033[31mpassenger server has been stopped!\033[0m"
    ;;
restart)
    cd $dir && (BUNDLE_GEMFILE="${dir}/Gemfile" bundle exec passenger-config restart-app $dir --ignore-app-not-running)
    echo -e "\033[32mpassenger server restart OK!\033[0m"
    ;;
*)
    echo -e "\033[35mUsage: ./passenger_server start|stop|restart\033[0m";;
esac
需要 登录 后方可回复, 如果你还没有账号请 注册新账号