将环境变量传递给无所事事的shell配置程序


Answers:


80

从Vagrant 1.8.0开始,您可以在这里忘记其他答案中的难看技巧。只需使用envshell配置程序(docs)的选项即可。

在您的Vagrantfile中像这样使用它:

config.vm.provision "shell", path: "provisionscript.sh", env: {"MYVAR" => "value"}

这将仅为配置脚本设置环境。如果您需要为VM中的所有进程设置一个持久性环境变量集,则这超出了Vagrant设置的范围,请查看此处:vagrant文​​件中的Shell环境变量仅在第一次传递时传递


在Vagrant 1.8.5中,该env参数仅在使用path脚本而不是inline脚本时才起作用。
spyle

1
@spyle我正在运行Vagrant 1.8.5(在Mac OS X 10.11.6上为VirtualBox 5.1.2)并env与一起使用inline
jonatan

嗯...我在这里想念什么吗?这对我不起作用: config.vm.provision :shell, path: "bootstrap.sh", env: {"MYSQL_DB_USERNAME"=>"django", "MYSQL_DB_PASSWORD"=>"supersecretpasswordwasreplaced"} 在另一侧 os.environ['MYSQL_DB_USERNAME'] 给出了一个关键错误:(
Tadhg

1
@Tadhg仔细检查您的Vagrant版本。也许问一个新问题,如果它不起作用?这可能是不相关的问题(例如,您的工具链中未保留的Vagrantfile版本或环境)。
gertvdijk

版本好。您是正确的,看了看文档,看来该配置只应在配置时起作用,所以我将其作为新问题进行了提问stackoverflow.com/questions/40270391/…–
Tadhg

42

这并不理想,但是我现在可以使用它:

config.vm.provision "shell" do |s|
    s.inline = "VAR1 is $1 and VAR2 is $2"
    s.args   = "#{ENV['VAR1']} #{ENV['VAR2']}"
end

3
您也可以替换s.inlines.path,并使用你会与通过相同的脚本:path => ""。(我的供应商有数百条线路,因此不适合内联。)
msanford 2014年

3
或者,将ruby方法与:args => ""参数一起使用,例如
msanford 2014年

4
你真的应该在里面有一个逗号s.args吗?
Marius Gedminas

16

我提供了用于基于CentOS的资源调配的解决方案:将所有必需的环境变量放在/etc/profile.d/vagrant.sh文件中,然后可以在任何资源调配脚本中访问它。

简而言之:

  $before_script = <<SCRIPT
  echo # vagrant profile script > /etc/profile.d/vagrant.sh
  echo export ENV_VAR1=foo.com/bar >> /etc/profile.d/vagrant.sh
  echo export ENV_VAR2=bar.com/foo >> /etc/profile.d/vagrant.sh
  chmod +x /etc/profile.d/vagrant.sh
SCRIPT

  $after_script = <<SCRIPT
    rm -rf /etc/profile.d/vagrant.sh
SCRIPT

  config.vm.provision "shell", inline: $before_script
  config.vm.provision "shell", path: "build.sh"
  config.vm.provision "shell", inline: $after_script

完整的Vagrantfile可以在这里找到 https://gist.github.com/bivas/6192d6e422f8ff87c29d


在Linux下为我工作(适用于基于Ubuntu的VM)。太棒了!
Nikos Alexandris

1
不过,现在有vagrantup.com/docs/provisioning/shell.html#env。我已经看过了,但是由于缺少示例,我跳过了它。一位同事指出,这是可行的。
Nikos Alexandris

1
@NikosAlexandris:看看我的回答:)
gertvdijk

16

为了后代(又名我再次用谷歌搜索)...可以通过env传递键值对:

box.vm.provision :shell do |s|
  s.env = {AWS_ACCESS_KEY:ENV['AWS_ACCESS_KEY'], AWS_SECRET_KEY:ENV['AWS_SECRET_KEY']}
  s.path = 'scripts/bootstrap.sh'
end

然后在您的脚本中引用它们:

export AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY}
export AWS_SECRET_ACCESS_KEY=${AWS_SECRET_KEY}

奖励功能:

Vagrant将处理环境变量值的引用,但键保持不变


另请参阅@gertvdijk发布的答案(发布时我的页面没有刷新)
Al Belsky

8

您可以#{ENV['VAR']}在内联脚本中使用,例如:

config.vm.provision "shell", inline: <<-END
  ...
  # Install my dotfiles are there.  If you're in a hurry you can do
  # SKIP_DOTFILES=1 vagrant up
  if ! [ -d /home/vagrant/dotfiles ] && [ -z '#{ENV['SKIP_DOTFILES']}']; then
    if ! [ -x /usr/bin/git ]; then
      DEBIAN_FRONTEND=noninteractive apt-get install -y git
    fi
    su - vagrant -c 'git clone https://github.com/mgedmin/dotfiles'
    su - vagrant -c 'dotfiles/install.sh'
  fi
  ...
  END

该示例取自有效的Vagrantfile。

这有一些缺点:如果$ VAR包含单引号,则事情会中断。


当然,我注意到@Bob我发布我的帖子后基本上提供了相同的答案(用NEW WAY位)。啊!
Marius Gedminas 2015年

7

如果有人最终在配置脚本的环境中寻找如何设置变量的方法,这对我很有用。

config.vm.provision :shell, :inline => <<-SH
  export GRAPHITE_HOST=192.168.33.10
  /vagrant/install_app_with_monitoring.sh
SH

请注意,这是假设您要像/vagrant在VM上一样共享工作目录,但这应该是默认目录。


但是为什么不在里面install_app_with_monitoring.sh呢?
Stephan Bijzitter

主要是将知识保持在同一位置。您可以在github.com/forty9ten/monitoring-with-graphite/blob/master / ...上看到一个示例。 通过将var保留在Vagrantfile中,可以轻松确保private_networkand之间的奇偶性GRAPHITE_HOST。甚至可以更进一步,并用于export GRAPHITE_HOST=#{ip}引用单个常见的红宝石变种。
Mat Schaffer

4

这些答案大多数似乎已过时。使用Vagrant 2.1.1可以为我工作:

  VAGRANTFILE_API_VERSION = "2" //...

  machine.vm.provision "shell", 
    env: {
      "ELASTIC_XMS" => servers["elastic"]["memory_xms"], 
      "ELASTIC_XMX" => servers["elastic"]["memory_xmx"]
    }, 
    inline: "sed -i -e \"s/-Xms.*/$ELASTIC_XMS/g\" /etc/elasticsearch/jvm.options"

2

流浪汉-ENV插件正是这样做的。使用它,您可以将环境变量添加到.env本地目录中的文件中,然后将其加载到Vagrant文件中。我的建议是将.env你的.gitignore,这样你有你的隐私保证。


1
插件于2015年过世,目前还不是。
Ligemer '17

1

这就是我的工作方式。

我从使用无所事事的木偶供应商方式转变为仅使用外壳供应商。我这样做主要是因为我想伪造不要以root身份运行,shell提供程序为您提供:privileged => false。

我的旧方式:

config.vm.provision :puppet do |puppet|
  puppet.module_path = ENV.fetch('MODULES_PATH', 'modules')
  puppet.manifests_path = ENV.fetch('MANIFESTS_PATH', 'manifests')
  puppet.manifest_file  = ENV.fetch('MANIFEST_FILE', 'site.pp')
  puppet.options = "--debug"
end

我的新方法:

config.vm.provision :shell, :privileged => false do |shell|
  shell.inline = "puppet apply --debug --modulepath '/vagrant/#{ENV.fetch('MODULES_PATH', 'modules')}' --detailed-exitcodes '/vagrant/#{ENV.fetch('MANIFESTS_PATH', 'manifests')}/#{ENV.fetch('MANIFEST_FILE', 'site.pp')}'"
end

1

您只需在文件中指定shell使用:inlineVagrantfile

config.vm.provision "shell", inline: %Q(/usr/bin/env FOO=1 BAR=1 bash /path/to/script.sh)

或从YAML文件加载一些额外的变量:

require 'yaml'
dir = File.dirname(File.expand_path(__FILE__))
vconfig = YAML::load_file("#{dir}/config.yml")
config.vm.provision "shell", inline: %Q(/usr/bin/env FOO=#{vconfig['foo']} bash /path/to/script.sh)

或者,您可以从命令行实现一些可选参数,例如:

# Parse optional arguments.
opts = GetoptLong.new(
  [ '--foo',  GetoptLong::OPTIONAL_ARGUMENT ], # With optional parameter.
  [ '--bar',  GetoptLong::OPTIONAL_ARGUMENT ], # With optional parameter.files.
)
opts.each do |opt, arg|
  case opt
    when '--foo'
      foo==arg
    when '--bar'
      bar=arg
  end
end

然后使用:opt['--foo'].to_s

另请参阅:如何在Vagrant上传递参数并将其纳入Chef Cookbook的范围内?


-2

这对我有用

VAGRANTFILE_API_VERSION = "2"

kettle_dir = ENV['KETTLE_DIR']
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
   config.vm.synced_folder kettle_dir, "/pentaho"
   config.vm.box = "ubuntu/trusty64"
end

您能否详细说明为什么这是正确的答案?
rfornal 2015年

这在Vagrantfile中使用了一个环境变量,但实际上并没有按照问题中的要求为配置者设置一个。
btubbs 2015年

-3

在ubutnu框上,我只是在bootstrap.sh中执行了以下操作:

echo "DBHOST=localhost" >> /etc/environment
echo "DBNAME=foo" >> /etc/environment
echo "DBUSER=root" >> /etc/environment
echo "DBPASSWD=root" >> /etc/environment
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.