Vagrant/VirtualBox VM 配置:rbenv 安装成功但随后在脚本中的使用失败

Vagrant/VirtualBox VM provisioning: rbenv installs successfully but subsequent uses in script fail

我正在使用 Vagrant + VirtualBox 为我的 Rails 应用设置虚拟机。我正在清理在 Vagrantfile 中引用的 .sh 配置脚本,如下所示:

config.vm.provision "shell", path: "script/provision-script.sh" 

提供脚本做了很多事情,但最后应该安装 rbenv Ruby 版本控制,然后使用 rbenv 安装 Ruby 2.2.1。提供脚本的那部分看起来像这样:

echo "setting up rbenv"
# execute the remaining commands as vagrant user, instead of root
sudo -H -u vagrant bash -c "git clone https://github.com/sstephenson/rbenv.git ~vagrant/.rbenv"
sudo -H -u vagrant bash -c "git clone https://github.com/sstephenson/ruby-build.git ~vagrant/.rbenv/plugins/ruby-build"
sudo -H -u vagrant bash -c "git clone https://github.com/sstephenson/rbenv-gem-rehash.git ~vagrant/.rbenv/plugins/rbenv-gem-rehash"
echo "setting up rbenv environment in bash"
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~vagrant/.bashrc
echo 'eval "$(rbenv init -)"' >> ~vagrant/.bashrc

# start new vagrant shell so rbenv will work
echo "building ruby"
su vagrant
rbenv install 2.2.1 && rbenv global 2.2.1 && rbenv rehash && cd /path/to/my/app && gem install bundler rake && rbenv rehash && bundle && rbenv rehash

rbenv install... 部分之前的所有内容都正常工作。安装 ruby 失败并出现以下错误:

==> default: setting up rbenv
==> default: Cloning into '/home/vagrant/.rbenv'...
==> default: Cloning into '/home/vagrant/.rbenv/plugins/ruby-build'...
==> default: Cloning into '/home/vagrant/.rbenv/plugins/rbenv-gem-rehash'...
==> default: setting up rbenv environment in bash
==> default: building ruby
==> default: /tmp/vagrant-shell: line 73: rbenv: command not found

然后脚本完成。我可以使用 vagrant ssh 打开虚拟机,然后成功地 运行 rbenv install 2.2.1,所以我猜测在配置期间实际上并没有启动新的 vagrant shell。我的印象是 su vagrant 就在 rbenv install 2.2.1 之前。

我该怎么做才能确保在此配置期间初始化新的 shell 并确保 rbenv 命令有效?

我很惊讶配置脚本会退出,因为 运行ning su vagrant 理论上应该在那个时候挂起脚本(你 运行ning 命令 su 通常不会自行退出)。

问题是您无法通过 运行ning su.[=28= 更改正在 运行ning shell 脚本 "on the fly" 的用户] 您唯一的选择是使用 sudo.

由于您刚刚使用新路径和其他设置更新了 .bashrc,因此您需要 运行 "sudo bash" 使用 -i 选项。这将强制 bash 模拟交互式登录 shell,因此读取 .bashrc 并加载 rbenv.

的正确路径

所以,像这样的东西应该会起作用:

echo "building ruby"
sudo -H -u vagrant bash -i -c 'rbenv install 2.2.1 ...'

我遇到了类似的问题,因为我试图 安装 rbenv 并且 vagrant provisioning 给我错误:

==> default: /tmp/vagrant-shell: line 10: rbenv: command not found

首先,了解 vagrant 供应脚本 运行 sudo 模式 非常重要。 因此,当我们在脚本中引用 ~/ 路径时,我们指的是 /root/ 路径而不是 /home/vagrant/ 路径。 问题是我正在为 root 用户安装 rbenv,然后尝试从 vagrant 用户调用 rbenv 命令,当然,它没有用!

所以,我所做的是将 vagrant 指定为 运行 不在 sudo 用户中的提供者,添加 privileged: false:

config.vm.provision :shell, privileged: false, inline: $script

然后在我的脚本中,我认为一切都是从 vagrant 用户调用的。 这里@Casper 的回答对我帮助很大,因为它只适用于指定: sudo -H -u vagrant bash -i -c '......'

Since you just updated .bashrc with a new path and other settings, you will want to run "sudo bash" with the -i option. This will force bash to simulate an interactive login shell, and therefore read .bashrc and load the correct path for rbenv.

下面是我最终的 Vagrantfile。

# -*- mode: ruby -*-
# vi: set ft=ruby :

$script = <<SCRIPT
  sudo apt-get -y update
  sudo apt-get -y install curl git-core python-software-properties ruby-dev libpq-dev build-essential nginx libsqlite3-0 libsqlite3-dev libxml2 libxml2-dev libxslt1-dev nodejs postgresql postgresql-contrib imagemagick

  git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
  echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
  echo 'eval "$(rbenv init -)"'               >> ~/.bashrc
  source ~/.bashrc

  git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
  sudo -H -u vagrant bash -i -c 'rbenv install 2.1.3'
  sudo -H -u vagrant bash -i -c 'rbenv rehash'
  sudo -H -u vagrant bash -i -c 'rbenv global 2.1.3'
  sudo -H -u vagrant bash -i -c 'gem install bundler --no-ri --no-rdoc'
  sudo -H -u vagrant bash -i -c 'rbenv rehash'
  sudo -u postgres createdb --locale en_US.utf8 --encoding UTF8 --template template0 development
  echo "ALTER USER postgres WITH PASSWORD \'develop\';" | sudo -u postgres psql
SCRIPT

VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.box = "hashicorp/precise64"
  config.vm.network "forwarded_port", guest: 3000, host: 3000

  # config.vm.provider :virtualbox do |vb|
  #   vb.customize ["modifyvm", :id, "--memory", "1024"]
  # end

  config.vm.provision :shell, privileged: false, inline: $script
end

希望对其他人有所帮助。

在 Vagrant Provisioning 过程中安装 rbenv 的另一个解决方案不同于两个 and 解决方案。

在使用 rbenv 命令之前使用下一个命令

export PATH="$HOME/.rbenv/bin:$PATH"
export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"
eval "$(rbenv init -)"

然后 运行 rbenv 安装命令而不 sudo -H -u vagrant bash -i -c

Bootstrap.sh 文件

#!/usr/bin/env bash

sudo apt-get update
echo "========================= install dependencies for install rbenv ==========================="
sudo apt-get install -y autoconf bison build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev libgdbm3 libgdbm-dev
echo "========================= install rbenv =========================================="
git clone https://github.com/rbenv/rbenv.git ~/.rbenv
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >>  ~/.bashrc
echo 'eval "$(rbenv init -)"' >>  ~/.bashrc
echo "========================= install ruby build plugin for rbenv ======================="
git clone https://github.com/rbenv/ruby-build.git  ~/.rbenv/plugins/ruby-build
echo 'export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"' >> ~/.bashrc
echo "========================= install ruby v2.5.0 =========================================="
export PATH="$HOME/.rbenv/bin:$PATH"
export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"
eval "$(rbenv init -)"
rbenv install 2.5.0
rbenv global 2.5.0
ruby -v
gem -v
echo "========================= install bundler dependencies manager for ruby ====================="
gem install bundler
rbenv rehash

然后 VagrantFile 文件将包含 vagrant 配置行

deploy_config.vm.provision :shell, privileged: false, path: "bootstrap.sh"

我的答案来自 Gits by @creisor