如何在“vagrant up”上传递参数并将其置于 Vagrantfile 的范围内?

Posted

技术标签:

【中文标题】如何在“vagrant up”上传递参数并将其置于 Vagrantfile 的范围内?【英文标题】:How to pass parameter on 'vagrant up' and have it in the scope of Vagrantfile? 【发布时间】:2012-12-16 22:46:41 【问题描述】:

我正在寻找一种将参数传递给 Chef 食谱的方法,例如:

$ vagrant up some_parameter

然后在其中一本 Chef 食谱中使用 some_parameter

【问题讨论】:

【参考方案1】:

您不能将任何参数传递给 vagrant。唯一的办法就是使用环境变量

MY_VAR='my value' vagrant up

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

【讨论】:

谢谢!我已经尝试过gist.github.com/4435297,我可以获得用户输入,但不知道如何将其传递给 Chef 食谱。现在将尝试将其与 ENV 结合起来 您也可以在 Vagrantfile 中访问该 ENV var 并将其放入 chef.json 哈希中(请参阅docs.vagrantup.com/v1/docs/provisioners/…) 是的,这样更方便。 vagrant的作者自己说要使用环境变量:github.com/mitchellh/vagrant/issues/2064 在powershell中你应该使用类似 $Env:MY_VAR='my value' |流浪【参考方案2】:

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

流浪文件

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 命令之前指定自定义选项以避免无效选项验证错误。

更多关于图书馆的信息here。

【讨论】:

自从我发布以来,我整天都在使用它。它工作得很好!你有什么问题? 似乎选项没有列在opts未处理:vagrant --custom-option=option destroy -fvagrant: invalid option -- f 是的,这行得通,而且恕我直言比第一个答案更优雅。 @BenjaminGauthier 文档说“空选项——(两个减号)用于结束选项处理。”。所以vagrant --custom-option=option -- up 应该够了 这不再适用于 Vagrant 2。除了自己的参数之外,它不接受任何参数。【参考方案3】:

可以从 ARGV 读取变量,然后在进入配置阶段之前将其从中删除。修改 ARGV 感觉很恶心,但我找不到任何其他命令行选项的方式。

流浪文件

# 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 会在删除额外的自定义参数后显示正确的数组。 这里一样,它不起作用...我在vagrant/embedded/gems/gems/vagrant-1.7.2/lib/vagrant/plugin/v2/command.rb 中放了一个puts "#ARGV" 行,它在删除Vagrantfile 中的相关参数之前打印该行,因此意味着删除是徒劳的,因为 ARGV 会在 ARGV 上进行任何操作之前传递给输出 An invalid option was specified 的验证器。【参考方案4】:

@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 --provision 要么 vagrant destroy -f 处理干净。

希望对你有帮助,

【讨论】:

【参考方案5】:
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

【讨论】:

这是一个很好的解决方案,但你能展示如何以非交互方式使用它吗?例如,是否可以通过管道传输参数?

以上是关于如何在“vagrant up”上传递参数并将其置于 Vagrantfile 的范围内?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Java 中添加组件并将其置于 JFrame 的前面?

如何在 Linux 上的 X Window System 中找到一个窗口并将其置于最前面?

如何找到活动的 PyQt 窗口并将其置于最前面

如何在`vagrant up`命令中指定提供程序?

React GraphQL Apollo 和 Redux。如何查询数据并将其置于 store 的 initialState 中?

如何使用 Cocoa api 启动应用程序并将其置于最前面?