每次虚拟机重启(vagrant up)后执行脚本或命令的Vagrant设置

40

我知道有一个配置脚本,但是我问的是另一个脚本。我想要一个在虚拟机每次重启后都能执行的脚本。

我正在使用shell脚本配置程序。

config.vm.provision :shell, path: "vagrant/bootstrap.sh"

我无法将我想在每次重启后运行的命令放入这个脚本中。

基本上,我希望当用户执行vagrant up时启动我的某个应用程序。

我的虚拟机是ubuntu 14.04 trusty,我找到的一个解决方案是在我的虚拟机上执行以下操作 -

sudo crontab -e
#add the following line 
@reboot sh /path/to/my_script_on_guest.sh

我可以尝试在我的配置脚本中完成这个任务,但是sudo crontab -e需要一个编辑器,我必须交互式地添加这一行。因为crontab文件不是固定的,所以我不知道是否可以像下面一样进行单行文件编辑:

echo '@reboot sh /path/to/my_script_on_guest.sh' >> crontab_file

我猜这可能是特定于客户操作系统的事情。

使用Vagrant可以实现吗?

编辑:从ssh provisioner更正为shell provisioner。

4个回答

69

你可以使用run: 'always'

config.vm.provision :shell, path: "vagrant/bootstrap.sh", run: 'always'

这将确保您的命令在每次启动虚拟机时都会被执行(vagrant up或vagrant reload)。

如果您只需要始终运行某些命令,则可以拆分您的脚本。

config.vm.provision :shell, path: "vagrant/bootstrap1.sh"
config.vm.provision :shell, path: "vagrant/bootstrap2.sh", run: 'always'
config.vm.provision :shell, path: "vagrant/bootstrap3.sh"

在机器首次配置时,脚本将按顺序运行,先是bootstrap1,然后是2,最后是3。

任何进一步的时间,只要您运行vagrant up(或reload),只有bootstrap2会运行。


谢谢。但是我的bootstrap.sh中还有其他不可重复的配置步骤。是否有其他的生命周期钩子? - Pranav Shukla
是的,清除一下你的脚本,将事情分割开来,让另一个脚本具有幂等性,不要总是运行 - 脚本按顺序运行。 - Frederic Henri
太完美了!这正是我所需要的。 - user1015214

5

我这里提供一个替代方案,使用vagrant triggers。考虑下面这个例子,直接来自他们的文档:

在销毁客户机之前,运行远程脚本将数据库保存到您的主机上:

Vagrant.configure("2") do |config|   
  config.vm.define "ubuntu" do |ubuntu|
    ubuntu.vm.box = "ubuntu"

    ubuntu.trigger.before :destroy do |trigger|
      trigger.warn = "Dumping database to /vagrant/outfile"
      trigger.run_remote = {inline: "pg_dump dbname > /vagrant/outfile"} 

      # or trigger.run = {...} to run the command on the host instead 
      # of guest
    end
  end 
end

还有一个相关的vagrant-triggers插件,你可以查看一下。


1
可以用这个:config.trigger.after :reload, :up do |trigger|。运行正常! - Cees Timmerman

1
我使用的是Ubuntu 18.04。触发器对我无效,所以我选择将后置脚本复制到虚拟机中,然后从主脚本中执行所需的后置操作。
config.trigger.before :provisioner_run, type: :hook do |t|
    t.info = "Before the provision!"
  end

  config.vm.provision "shell" do |s|
    s.inline = "echo $1  "
    s.args   = [" '--->' Provisioning the environment!"]
  end 
  config.vm.provision "file", source: "scripts/post-provision/.", destination: "/home/vagrant"
  config.vm.provision "shell", path: "scripts/install.sh"
  # config.vm.provision "shell", path: "scripts/bootstrap.sh", run: 'always'

  # config.trigger.after :up do |trigger|
  #   trigger.info = "Installing Monitoring Stack..."
  #   trigger.run_remote = {path: "./install-monitor-stack.sh"}
  # end
end

主脚本内容使用 exec 刷新新 shell。您也可以使用

reset


sudo chmod  +x *.sh
exec /home/vagrant/install-monitor-stack.sh
exec /home/vagrant/bootstrap.sh

0

我有两个配置外壳的部分。一个是普通的,另一个带有run: always参数。这对我来说很好用。在我的例子中,它在我的vagrant映像上启动了nginx。我已经在inline之前添加了run参数。当放置在最后(在SHELL之后)时,它不起作用。

config.vm.provision "shell", run: "always", inline: <<-SHELL
    sudo systemctl start nginx
SHELL

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