如何在“vagrant up”命令中传递参数并使其在Vagrantfile的作用域内?

91

我正在寻找一种像这样将参数传递给Chef cookbook的方法:

$ vagrant up some_parameter

然后在其中一个Chef烹饪书中使用some_parameter参数。

5个回答

120
您无法向Vagrant传递任何参数。唯一的方法是使用环境变量。
MY_VAR='my value' vagrant up

使用 ENV['MY_VAR'] 在配方中。


1
谢谢!我已经尝试了https://gist.github.com/4435297,我可以获取用户输入,但不知道如何将其传递到Chef cookbook中。现在将尝试将其与ENV结合使用。 - Wojciech Bednarski
7
你可以在 Vagrantfile 中访问该 ENV 变量,并将其放入 chef.json 哈希表中(参见http://docs.vagrantup.com/v1/docs/provisioners/chef_solo.html#json_configuration) - StephenKing
是的,那更方便。 - Draco Ater
5
vagrant 的作者本人建议使用环境变量:https://github.com/mitchellh/vagrant/issues/2064 - Alexander Bird
在PowerShell中,您应该使用类似以下的命令: $Env:MY_VAR='my value' | vagrant up - Alberto R.
另一个答案 - https://dev59.com/0WYq5IYBdhLWcg3w4EZx#31070025 应该被接受为正确答案。 - slm

78

您还可以包含 GetoptLong Ruby 库,它允许您解析命令行选项。

Vagrantfile

require 'getoptlong'

opts = GetoptLong.new(
  [ '--custom-option', GetoptLong::OPTIONAL_ARGUMENT ]
)

customParameter=''

opts.each do |opt, arg|
  case opt
    when '--custom-option'
      customParameter=arg
  end
end

Vagrant.configure("2") do |config|
             ...
    config.vm.provision :shell do |s|
        s.args = "#{customParameter}"
    end
end

然后,您可以运行:

$ vagrant --custom-option=option up
$ vagrant --custom-option=option provision

注意:在vagrant命令之前指定自定义选项,以避免无效选项验证错误。

有关该库的更多信息在此处


1
我自从发帖以来整天都在使用它。它运行得非常好!你遇到了什么问题? - Benjamin Gauthier
14
似乎选项未列在“opts”中,未被处理:`vagrant --custom-option=option destroy -f` `vagrant:无效选项--f` - Renat Zaripov
2
是的,这个方法可行,而且我认为比第一个答案更优美。 - davidav
2
@BenjaminGauthier 文档中说:“空选项--(两个减号)用于结束选项处理。” 因此,vagrant --custom-option=option -- up 应该就足够了。 - CESCO
3
这个在Vagrant 2中不再起作用了。它除了自己的参数之外不接受任何其他参数。 - Jens Baitinger
显示剩余8条评论

24

在进行配置阶段之前,可以从ARGV中读取变量,然后将其删除。修改ARGV感觉不太好,但我找不到其他处理命令行选项的方法。

Vagrantfile

# Parse options
options = {}
options[:port_guest] = ARGV[1] || 8080
options[:port_host] = ARGV[2] || 8080
options[:port_guest] = Integer(options[:port_guest])
options[:port_host] = Integer(options[:port_host])

ARGV.delete_at(1)
ARGV.delete_at(1)

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  # Create a forwarded port mapping for web server
  config.vm.network :forwarded_port, guest: options[:port_guest], host: options[:port_host]

  # Run shell provisioner
  config.vm.provision :shell, :path => "provision.sh", :args => "-g" + options[:port_guest].to_s + " -h" + options[:port_host].to_s

provision.sh

port_guest=8080
port_host=8080

while getopts ":g:h:" opt; do
    case "$opt" in
        g)
            port_guest="$OPTARG" ;;
        h)
            port_host="$OPTARG" ;;
    esac
done

这对我似乎不起作用。我总是收到错误消息“指定了无效选项”。在删除额外的自定义参数后,执行puts ARGV可以正确显示数组。 - majkinetor
1
同样的问题,它不起作用...我在vagrant/embedded/gems/gems/vagrant-1.7.2/lib/vagrant/plugin/v2/command.rb中添加了一行puts "#{ARGV}"代码,并且它会在删除Vagrantfile中相关参数之前打印该行,这意味着删除是徒劳的,因为ARG被传递给验证器,验证器在对ARGV进行任何操作之前输出“指定了无效选项”。 - BogdanSorlea

9
@benjamin-gauthier的GetoptLong方案非常巧妙,与Ruby和Vagrant范式非常契合。
然而,为了处理Vagrant参数(例如vagrant destroy -f)的清理操作,需要添加一行额外的代码。
require 'getoptlong'

opts = GetoptLong.new(
  [ '--custom-option', GetoptLong::OPTIONAL_ARGUMENT ]
)

customParameter=''

opts.ordering=(GetoptLong::REQUIRE_ORDER)   ### this line.

opts.each do |opt, arg|
  case opt
    when '--custom-option'
      customParameter=arg
  end
end

这使得当自定义选项被处理时,该代码块可以暂停。因此现在,vagrant --custom-option up --provisionvagrant destroy -f 可以得到清晰的处理。

希望这能帮到您,


这非常有帮助,谢谢! - Mina Ghobrial

4
Vagrant.configure("2") do |config|

    class Username
        def to_s
            print "Virtual machine needs you proxy user and password.\n"
            print "Username: " 
            STDIN.gets.chomp
        end
    end

    class Password
        def to_s
            begin
            system 'stty -echo'
            print "Password: "
            pass = URI.escape(STDIN.gets.chomp)
            ensure
            system 'stty echo'
            end
            pass
        end
    end

    config.vm.provision "shell", env: {"USERNAME" => Username.new, "PASSWORD" => Password.new}, inline: <<-SHELL
        echo username: $USERNAME
        echo password: $PASSWORD
SHELL
    end
end

1
这是一个不错的解决方案,但您能展示如何以非交互方式使用它吗?例如,是否可以将参数进行管道传输? - Fuzzy Logic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接