Install Bundler gem using Ansible

2019-01-22 12:31发布

问题:

I am trying to install Bundler on my VPS using Ansible.

I already have rbenv set up and the global ruby is 2.1.0.

If I SSH as root into the server and run gem install bundler, it installs perfectly.

I have tried the following three ways of using Ansible to install the Bundler gem and all three produce no errors, but when I SSH in and run gem list, Bundler is nowhere to be seen.

Attempt 1:

---
- name: Install Bundler
  shell: gem install bundler

Attempt 2:

---
- name: Install Bundler
  shell: gem install bundler

Attempt 3:

---
- name: Install Bundler
  gem: name=bundler
       state=latest

I have also tried the last attempt with user_install=yes and also with user_install=no and neither make any difference.

Any ideas how I can get it to install Bundler correctly via Ansible?

I've been working on this for a little while now and I have 1 ruby version installed: 2.1.0 and ahve found that the shims directory for rbenv does not contain a shim for bundle.

Should a shim for bundle be in there? I'm just getting confused as to why capistrano cannot find the bundle command as it's listed when I run sudo gem list but NOT when I run gem list?

root@weepingangel:/usr/local/rbenv/shims# echo $PATH
/usr/local/rbenv/shims:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
root@weepingangel:/usr/local/rbenv/shims# gem environment
RubyGems Environment:
  - RUBYGEMS VERSION: 2.2.0
  - RUBY VERSION: 2.1.0 (2013-12-25 patchlevel 0) [x86_64-linux]
  - INSTALLATION DIRECTORY: /usr/local/rbenv/versions/2.1.0/lib/ruby/gems/2.1.0
  - RUBY EXECUTABLE: /usr/local/rbenv/versions/2.1.0/bin/ruby
  - EXECUTABLE DIRECTORY: /usr/local/rbenv/versions/2.1.0/bin
  - SPEC CACHE DIRECTORY: /root/.gem/specs
  - RUBYGEMS PLATFORMS:
    - ruby
    - x86_64-linux
  - GEM PATHS:
     - /usr/local/rbenv/versions/2.1.0/lib/ruby/gems/2.1.0
     - /root/.gem/ruby/2.1.0
  - GEM CONFIGURATION:
     - :update_sources => true
     - :verbose => true
     - :backtrace => false
     - :bulk_threshold => 1000
     - :sources => ["http://gems.rubyforge.org", "http://gems.github.com"]
     - "gem" => "--no-ri --no-rdoc"
  - REMOTE SOURCES:
     - http://gems.rubyforge.org
     - http://gems.github.com
  - SHELL PATH:
     - /usr/local/rbenv/versions/2.1.0/bin
     - /usr/local/rbenv/libexec
     - /usr/local/rbenv/shims
     - /usr/local/sbin
     - /usr/local/bin
     - /usr/sbin
     - /usr/bin
     - /sbin
     - /bin
     - /usr/games

Any ideas?

So, I think the two main problems I have:

  1. Why is bundler only visible when I run sudo gem list?

  2. My deploy is saying:

    INFO [18d5838c] Running /usr/bin/env bundle install --binstubs  
    /var/rails_apps/neiltonge/shared/bin --path  
    /var/rails_apps/neiltonge/shared/bundle --without development test
    --deployment --quiet on 188.226.159.96 DEBUG [18d5838c] Command: cd /var/rails_apps/neiltonge/releases/20140301205432 && ( PATH=$PATH
    /usr/bin/env bundle install --binstubs
    /var/rails_apps/neiltonge/shared/bin --path
    /var/rails_apps/neiltonge/shared/bundle --without development test
    --deployment --quiet ) DEBUG [18d5838c]     /usr/bin/env: bundle: No such file or directory
    

    and this is my $PATH:

    /usr/local/rbenv/shims:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
    

Why can't bundle be located?

回答1:

The problem is that, when running gem install bundler via ansible, you're not initializing rbenv properly, since rbenv init is run in .bashrc or .bash_profile. So the gem command used is the system one, not the one installed as a rbenv shim. So whenever you install a gem, it is installed system-wide, not in your rbenv environment.

To have rbenv initialized properly, you must execute bash itself and explicitely state that it's a login shell, so it reads it's initialization files :

ansible your_host -m command -a 'bash -lc "gem install bundler"' -u your_rbenv_user 

Leave the -u your_rbenv_user part if you really want to do this as root.

If the above command works, you can easily turn it into a playbook action :

- name: Install Bundler
  become_user: your_rbenv_user
  command: bash -lc "gem install bundler"

It's cumbersome, but it's the only way I found so far.



回答2:

Since Ansible 1.3 following native solution is possible:

- name: requirements for installing gems
  apt:
    name: {{ item }}
  with_items:
    - ruby
    - ruby-dev
    - make

- name: install gem with proper $PATH
  gem:
    name: xyz
    user_install: no

Mention the user_install parameter! Additionally some dependecies installed by the bundler could need following further package dependencies:

  • zlib1g-dev


回答3:

I've met the similar environment issue when I tried to run commands as another user. As mentioned in this feature request you have two options to execute your command in login shell (that will load user environment). For example i'ld like to install bundler as rails user:

- name: Install Bundler
  shell: gem install bundler
  sudo_user: rails -i

or

- name: Install Bundler
  command: sudo -iu rails gem install bundler


回答4:

This Worked for me:

- name: rubygems | install bundler
  shell: gem install bundler

- name: rbenv | rehash
  shell: RBENV_ROOT={{ rbenv_root }} rbenv rehash

Sometimes after installing bundler, with rbenv on the system, you need to update your $PATH by runing rbenv rehash. I just tried the same thing with ansible, and it worked. Bundler is available in my $PATH after rehash.



回答5:

The cleanest and quickest way to install bundler using Ansible is this:

Simply install rbenv by using the role https://github.com/zzet/ansible-rbenv-role and by configuring its plugins like so (obviously, there are more parameters to configure than just the plugins):

rbenv_plugins:
- { name: 'ruby-build',
    repo: 'https://github.com/rbenv/ruby-build.git',
    version: master }
- { name: 'rbenv-default-gems',
    repo: 'https://github.com/rbenv/rbenv-default-gems.git',
    version: master }

The included plugin rbenv-default-gems will add bundler by default and into the right directory during the installation process of the version of ruby you will have spcecified.

Then make sure bundler is in PATH.

That's it.