【问题标题】:Pass environment variables to vagrant shell provisioner将环境变量传递给 vagrant shell 配置器
【发布时间】:2013-11-08 00:14:17
【问题描述】:

如果您使用的是 Ruby 配置器,在调用 vagrant up 时传递环境变量看起来很简单:

VAR=123 vagrant up

在 Vagrantfile 中:

ENV['VAR']

如何使用 :shell 配置程序执行此操作?简单地这样做似乎不起作用:

$VAR

【问题讨论】:

    标签: vagrant environment-variables


    【解决方案1】:

    这些答案中的大多数似乎已经过时了。使用 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】:

      Since Vagrant 1.8.0 您可以在这里忘记其他答案中的丑陋黑客。只需将 env 选项用于 shell 配置程序 (docs)。

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

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

      这将仅为配置脚本设置环境。如果您需要为 VM 中的所有进程设置持久环境变量,这超出了 Vagrant 配置的范围,请查看此处:Shell environment variables in vagrant files are only passed on first up

      【讨论】:

      • 在 Vagrant 1.8.5 中,env 参数似乎仅在使用 path 脚本时有效,而不是 inline 脚本。
      • @spyle 我正在运行 Vagrant 1.8.5(在 Mac OS X 10.11.6 上使用 VirtualBox 5.1.2),envinline 一起使用。
      • 嗯...我在这里遗漏了什么吗?这对我不起作用:config.vm.provision :shell, path: "bootstrap.sh", env: {"MYSQL_DB_USERNAME"=>"django", "MYSQL_DB_PASSWORD"=>"supersecretpasswordwasreplaced"} 另一方面os.environ['MYSQL_DB_USERNAME'] 给出了一个关键错误:(
      • @Tadhg 仔细检查您的 Vagrant 版本。如果它不起作用,也许会问一个新问题?这可能是一个不相关的问题(例如,您的工具链中未保留的 Vagrantfile 版本或环境)。
      • 版本不错。你是对的,看文档,似乎这个配置应该只在配置时工作,所以我把这个作为一个新问题问了stackoverflow.com/questions/40270391/…
      【解决方案3】:

      在一个 ubutnu 盒子上,我只是在 bootstrap.sh 中执行了以下操作:

      echo "DBHOST=localhost" >> /etc/environment
      echo "DBNAME=foo" >> /etc/environment
      echo "DBUSER=root" >> /etc/environment
      echo "DBPASSWD=root" >> /etc/environment
      

      【讨论】:

        【解决方案4】:

        为了后代(如果我再次用谷歌搜索它)...可以通过 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 发布的答案(发布时我的页面没有刷新)
        【解决方案5】:

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

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

        【讨论】:

        • 您也可以将s.inline 替换为s.path 并使用与:path => "" 相同的脚本。 (我的供应商有数百行,因此不适合内联。)
        • 或者,使用带有:args => "" 参数like so 的ruby 方法。
        • s.args里面真的应该加逗号吗?
        【解决方案6】:

        vagrant-env 插件正是这样做的。使用它,您可以将环境变量添加到本地目录中的.env 文件中,该文件将加载到Vagrant 文件中。我建议将.env 保留在您的.gitignore 中,这样您的隐私就会得到保障。

        【讨论】:

        • 插件早在 2015 年就死了,这不是最新的。
        【解决方案7】:

        您可以在Vagrantfile 文件中使用inline 简单地为shell 指定:

        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

        另请参阅:How to pass parameter on Vagrant up and have it in the scope of Chef cookbook?

        【讨论】:

          【解决方案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 基本上提供了相同的答案(以新的方式)就在我发布我的之后。啊!
          【解决方案9】:

          这是我的工作方式。

          我从使用 vagrant puppet provisioner 方式转变为仅使用 shell provisioner。我这样做主要是因为我不想以 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
          

          【讨论】:

            【解决方案10】:

            这对我有用

            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
            

            【讨论】:

            • 你能详细说明为什么这是正确答案吗?
            • 这在 Vagrantfile 中使用了一个环境变量,但实际上并没有按照问题中的要求为供应商设置一个。
            【解决方案11】:

            我为基于 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)。太棒了!
            • 虽然,现在有vagrantup.com/docs/provisioning/shell.html#env。我看过它,但由于缺乏示例,我跳过了它。一位同事指出它有效。
            • @NikosAlexandris:看我的回答:)
            【解决方案12】:

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

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

            请注意,这假设您在 VM 上以 /vagrant 的身份共享您的工作目录,但这应该是默认设置。

            【讨论】:

            • 但是为什么不在 install_app_with_monitoring.sh 里面做呢?
            • 主要是把知识放在一个地方。你可以在这里看到一个例子 github.com/forty9ten/monitoring-with-graphite/blob/master/… 通过将 var 保存在 Vagrantfile 中,很容易确保 private_networkGRAPHITE_HOST 之间的奇偶校验。甚至可以更进一步,使用 export GRAPHITE_HOST=#{ip} 来引用单个常见的 ruby​​ 变量。
            猜你喜欢
            • 2013-03-05
            • 2014-09-15
            • 2017-03-06
            • 2013-12-29
            • 2018-02-04
            • 2015-09-18
            • 2021-09-05
            • 2020-03-27
            • 2017-03-30
            相关资源
            最近更新 更多