原文位址
雖然 Vagrant 提供了用于配置虛拟機的多個選項,但是有标準用法,好多知識點對這個 provisioner 是通用的。
配置
首先,Vagrantfile 中配置的每個 provisioner 都使用
config.vm.provision
方法調用。例如,使用 shell 配置程式:
Vagrant.configure("2") do |config|
# ... other configuration
config.vm.provision "shell", inline: "echo hello"
end
每個 provisioner 都有類型,例如“shell”,是第一個參數。後面緊跟着用于配置特定 provisioner 的鍵值對。除了基本的鍵值對,還可以使用 Ruby 塊這種類似變量定義的文法。下面示例跟上面的相同:
Vagrant.configure("2") do |config|
# ... other configuration
config.vm.provision "shell" do |s|
s.inline = "echo hello"
end
end
基于塊的文法的好處是,使用多個選項可以大大提高可讀性。此外,一些 provisioner (如 Chef provisioner)具有可在該塊内調用的特殊方法,以簡化無法使用鍵值對進行的配置,此文法還可以将參數傳遞給 shell 腳本。
使用
=
樣式設定的屬性可以在單行中設定,例如上面的
inline ="echo hello"
。如果樣式更像是一個函數調用,比如
add_recipe "foo"
,那麼這不能在一行中指定。
Provisioner 也可以被命名(自 1.7.0 起)。這些名稱可以用于輸出以及覆寫 provisioner 設定(下面會進一步介紹)。下面顯示了一個命名過的 provisioner:
Vagrant.configure("2") do |config|
# ... other configuration
config.vm.provision "bootstrap", type: "shell" do |s|
s.inline = "echo hello"
end
end
命名 provisioner 很簡單。
config.vm.provision
的第一個參數就是名字,後面的
type
參數用于指定 provisioner 類型,例如
type: "shell"
。
運作 Provisioner
provisioner 在三種情況下運作:第一次
vagrant up
,
vagrant provision
和
vagrant reload --provision
如果不想運作 provisioner,可以将
--no-provision
标志傳遞給 up 和 reload。類似,也可以傳遞
--provision
來強制執行 provisioning。
如果有多個 provisioner,要運作指定的 provisioner 時,可以使用
--provision-with
标志。例如,同時又 shell 和 Puppet 配置程式時,如果隻想運作 shell,可以執行
vagrant provision --provision-with shell
。
--provision-with
的參數可以是 provisioner 的類型(例如 shell)或指令(例如上面示例中的 bootstrap)。
運作一次還是一直運作
預設情況下,除非設定了
--provision
标志,否則 provisioner 配置程式隻在上次
vagrant destroy
後的第一次
vagrant up
期間運作一次。
或者,可以配置 provisioner 以在每次啟動或重新加載時運作。隻有在顯式指定
--no-provision
标志時才會運作它們。為此,請将 run 選項設定為“always”,如下所示:
Vagrant.configure("2") do |config|
config.vm.provision "shell", inline: "echo hello",
run: "always"
end
如果想在“提示消息”中提示使用者有可選的 provisioner,或者 provisioner 在啟動之前依賴其他配置,也可以将 run 選項設定為“never”。之後可以通過
vagrant provision --provision-with bootstrap
調用。
如果使用塊格式,則必須在塊外指定 run 這個選項,如下所示:
Vagrant.configure("2") do |config|
config.vm.provision "shell", run: "always" do |s|
s.inline = "echo hello"
end
end
多個 Provisioner
可以使用多個
config.vm.provision
方法來定義多個 provisioner。這些 provisioner 将按照他們定義的順序運作。常見的使用常見是:使得 shell 腳本可以引導某些系統,以便其他設定程式可以稍後進行。
如果在多個“scope”級别定義 provisioner(例如在配置塊中全局化,然後在多機器定義中,然後可能在 provider 特定的覆寫中),那麼外部 scope 将始終在任何内部 scope 之前運作。例如,在下面的 Vagrantfile 中:
Vagrant.configure("2") do |config|
config.vm.provision "shell", inline: "echo foo"
config.vm.define "web" do |web|
web.vm.provision "shell", inline: "echo bar"
end
config.vm.provision "shell", inline: "echo baz"
end
provisioner 的順序是列印“foo”,“baz”,然後是“bar”。
使用多個 provisioner 時,使用
--provision-with
設定和名稱可以更好地控制運作的内容和時間。
覆寫 Provisioner 的設定
警告:進階主題! Provisioner 覆寫是一個進階主題,如果已經在使用多機器和/或提供程式覆寫,那麼它非常有用。 如果你剛剛開始使用 Vagrant,可以放心地跳過。
在使用 multi-machine 或特定于 provider 的功能時,可能需要在 Vagrantfile 的全局配置範圍中定義通用 provisioner,但在内部覆寫它們的某些方面。Vagrant 允許你這樣做,但有一些細節需要考慮。
要覆寫設定,必須為 provisioner 配置設定一個名稱。
Vagrant.configure("2") do |config|
config.vm.provision "foo", type: "shell",
inline: "echo foo"
config.vm.define "web" do |web|
web.vm.provision "foo", type: "shell",
inline: "echo bar"
end
end
在上面,隻會顯示“bar”,因為内聯設定會重載外部provisioner。這個重載隻在該範圍内有效:“web”虛拟機。如果定義了另一個虛拟機,它仍會回顯“foo”,除非它本身也重載了 provisioner。
順序要小心。當覆寫子範圍中的 provisioner 時,provisioner 将在該點運作。在下面的例子中,輸出将是“foo”,然後是“bar”:
Vagrant.configure("2") do |config|
config.vm.provision "foo", type: "shell",
inline: "echo ORIGINAL!"
config.vm.define "web" do |web|
web.vm.provision "shell",
inline: "echo foo"
web.vm.provision "foo", type: "shell",
inline: "echo bar"
end
end
如果想保留原來的順序,可以指定
preserve_order:true
标志:
Vagrant.configure("2") do |config|
config.vm.provision "do-this",
type: "shell",
preserve_order: true,
inline: "echo FIRST!"
config.vm.provision "then-this",
type: "shell",
preserve_order: true,
inline: "echo SECOND!"
end