部署Rails至CentOS时,无法用Capistrano重置VERSION环境变量
看来你碰到了CentOS服务器上的VERSION环境变量和Capistrano部署冲突的问题,我来帮你分析下为啥你之前的钩子没生效,以及怎么解决:
为什么你的原有方法不生效?
你在before :migrating钩子任务里设置set :default_env, { VERSION: nil },但Capistrano的:default_env是在建立SSH会话之初就加载应用的,等before :migrating钩子触发时,SSH会话已经建立好了,这个时候再修改:default_env根本不会影响当前会话里的后续任务(比如db:migrate),所以这个设置完全没起作用。
可行的解决方案
方案1:全局覆盖VERSION环境变量(最简单)
直接在你的deploy.rb顶层(不要放在任何namespace或task里)添加这段代码:
# 全局覆盖VERSION变量为nil,所有Capistrano执行的任务都会生效 set :default_env, fetch(:default_env, {}).merge(VERSION: nil)
这样Capistrano在启动每个SSH会话时,都会自动把VERSION设为nil,不管是migrate还是其他部署任务,都不会再受服务器原有VERSION变量的干扰。
方案2:仅在migrate前临时取消VERSION
如果你不想全局修改环境变量,只想针对db:migrate任务处理,可以修改钩子任务,直接在服务器上执行unset命令,并且确保这个操作和migrate在同一个环境里生效:
namespace :deploy do before :migrating, :unset_version_for_migrate task :unset_version_for_migrate do on roles(:db) do # 注意migrate任务一般是在db角色执行,不是app角色 within release_path do # 用with方法直接覆盖环境变量,执行migrate时生效 with VERSION: nil do # 这里可以先验证变量是否被覆盖 execute :echo, "$VERSION" end end end end end
或者更直接,重写migrate任务的执行逻辑,强制覆盖环境变量:
namespace :deploy do # 增强原有migrate任务,添加环境变量覆盖 Rake::Task["deploy:migrate"].enhance do on roles(:db) do within release_path do with VERSION: nil, rails_env: fetch(:rails_env) do execute :rake, "db:migrate" end end end end end
方案3:在服务器端临时取消(适合临时测试)
如果你只是想快速验证问题,也可以在服务器上的~/.bashrc或~/.bash_profile里添加unset VERSION,但这个会影响所有登录用户的会话,不推荐长期使用,还是用Capistrano层面的控制更安全。
验证是否生效
不管用哪种方案,都可以在钩子或任务里添加execute :echo, "$VERSION"来验证变量是否被正确设置为nil,这样能快速确认问题是否解决。
内容的提问来源于stack exchange,提问作者dp7

