AWS CodeDeploy部署Rails到Ubuntu20.0 EC2时Ruby版本不匹配
问题根因
CodeDeploy代理执行部署脚本时默认使用非交互、非登录shell,不会自动加载rbenv的环境初始化逻辑,因此调用gem、bundle等命令时,命中的是系统全局路径预装的Ruby 2.7,既不会识别项目目录下的.ruby-version版本声明,也不会走rbenv的版本垫片(shim)逻辑,之前在脚本里写的版本切换操作不生效,本质是执行命令时根本没用到rbenv管理的Ruby版本。
可直接落地的修复步骤
- 先确认rbenv的实际安装路径:如果是用ec2-user用户安装的rbenv,默认路径是
/home/ec2-user/.rbenv;如果是root用户安装的,默认路径是/root/.rbenv,后续配置替换成实际路径即可。 - 不要在appspec.yml的hooks段直接写裸的
bundle install、rails db:migrate这类命令,所有Ruby相关的部署脚本开头必须先加载rbenv环境,参考脚本模板:
#!/bin/bash set -e # 任意命令报错则终止部署 # 加载rbenv环境 export RBENV_ROOT="/home/ec2-user/.rbenv" export PATH="$RBENV_ROOT/shims:$RBENV_ROOT/bin:$PATH" eval "$(rbenv init -)" # 切到CodeDeploy部署的项目目录,CodeDeploy会自动注入环境变量$DEPLOYMENT_GROUP_DIR指向当前部署路径 cd $DEPLOYMENT_GROUP_DIR # 执行原有部署逻辑 bundle install --deployment --without development test bundle exec rails db:migrate RAILS_ENV=production bundle exec rails assets:clobber RAILS_ENV=production bundle exec rails assets:precompile RAILS_ENV=production
- 修改appspec.yml的hooks配置,指定脚本的执行用户为安装rbenv、Ruby 2.5.7的用户(比如ec2-user),不要用默认的root用户执行,避免权限和路径找不到的问题,配置示例:
hooks: AfterInstall: - location: scripts/deploy.sh timeout: 300 runas: ec2-user
- 不需要额外执行
rbenv global 2.5.7或者rbenv local 2.5.7,只要rbenv环境加载正常,它会自动识别项目根目录的.ruby-version文件切换到对应版本。
本地预验证方法
配置完先在EC2实例上模拟CodeDeploy的执行环境跑测试,避免反复触发部署浪费时间,执行以下命令:
sudo su -s /bin/bash ec2-user -c 'export RBENV_ROOT="/home/ec2-user/.rbenv"; export PATH="$RBENV_ROOT/shims:$RBENV_ROOT/bin:$PATH"; eval "$(rbenv init -)"; cd /你的测试项目路径; ruby -v; bundle -v'
如果命令返回Ruby版本为2.5.7,没有版本报错,说明配置正确,再触发CodeDeploy部署即可。
常见踩坑:不要把rbenv的环境变量配置写到
.bashrc、.bash_profile里就觉得万事大吉,非交互shell默认不会加载这两个文件的配置,必须在执行部署命令前显式加载rbenv初始化逻辑。
内容的提问来源于stack exchange,提问作者Gurpreet Singh
相关产品推荐
相关产品推荐

