rbenv与ruby-build插件配合问题:Puppet执行rbenv install命令报错
我之前也踩过一模一样的坑!核心问题是Puppet的exec资源运行时的环境,和你手动登录shell的环境完全不是一回事——rbenv的初始化逻辑没触发,自然识别不到plugins目录里的ruby-build插件。给你几个亲测有效的解决办法:
先确认ruby-build的安装位置是否正确
手动登录apps用户,去/home/apps/.rbenv/plugins目录下看看,有没有ruby-build这个文件夹?如果Puppet把ruby-build装到了别的路径(比如/usr/local/share/ruby-build),那得让Puppet给它整个软链到rbenv的plugins目录里,比如用Puppet的file资源来做:file { '/home/apps/.rbenv/plugins/ruby-build': ensure => link, target => '/实际的ruby-build安装路径', user => 'apps', group => 'apps', }只有ruby-build在rbenv的plugins目录下,rbenv才会把它当成插件加载。
让Puppet的exec模拟登录shell环境
你手动执行rbenv install时,shell会加载~/.bashrc或者~/.profile里的rbenv初始化脚本(比如eval "$(rbenv init -)"),但Puppet的exec默认是非登录、非交互shell,根本不会碰这些脚本。所以可以在exec的命令里,先手动触发rbenv的初始化:exec { 'install-ruby-with-rbenv': command => "bash -lc 'export RBENV_ROOT=/home/apps/.rbenv; eval \"$(rbenv init -)\"; rbenv install ${ruby_version}'", path => '/usr/bin:/bin:/home/apps/.rbenv/bin', user => 'apps', group => 'apps', environment => ['HOME=/home/apps'], unless => "bash -lc 'rbenv versions | grep ${ruby_version}'", }这里用
bash -lc模拟登录shell,同时显式指定RBENV_ROOT和HOME,确保rbenv能找到自己的配置和插件。一定要指定exec的运行用户
别忘记给exec加上user => 'apps'和group => 'apps'!你手动执行是用apps用户,要是Puppet默认用root跑,它会去读root用户的rbenv配置,自然找不到apps用户目录下的ruby-build插件,权限也会出问题。兜底方案:直接调用ruby-build脚本
要是上面的方法都不生效,其实可以绕开rbenv的命令,直接调用ruby-build的可执行脚本完成安装:exec { 'install-ruby-directly': command => "/home/apps/.rbenv/plugins/ruby-build/bin/ruby-build ${ruby_version} /home/apps/.rbenv/versions/${ruby_version}", user => 'apps', group => 'apps', unless => "test -d /home/apps/.rbenv/versions/${ruby_version}", } exec { 'rbenv-rehash-after-install': command => 'rbenv rehash', path => '/home/apps/.rbenv/bin:/usr/bin', user => 'apps', group => 'apps', require => Exec['install-ruby-directly'], }安装完之后记得执行
rbenv rehash更新shims,这样之后用rbenv切换版本就正常了。
最后给你个小技巧:可以先在Puppet里加个临时的exec,打印一下运行环境:
exec { 'print-env': command => 'bash -lc "env" > /home/apps/puppet-env.txt', user => 'apps', }
然后对比手动登录shell后env输出的内容,看看RBENV_ROOT、PATH、HOME这些关键变量有没有差异,很快就能定位到问题所在~




