37

Я хотел бы запустить bash-скрипт на хост-машине, когда vagrant подготовит сервер.

Каков будет лучший способ достижения этого?

5 ответов5

29

Как минимум два плагина, которые должны помочь:

Если вас не волнует, что скрипт запускается (почти) во всех vagrant командах, вы также можете просто выложить (или использовать какую-либо рубиновую магию) в Vagrantfile:

system('./myscript.sh')

Vagrant.configure('2') do |config|
  # ...
end
23

Простое (и полное) решение

(Я говорю завершено, потому что принятый ответ не проверяет, использует ли пользователь vagrant up. Поэтому скрипт выполняется для каждой команды, а это не то, что хочет OP.)

Однако есть простое решение.

ARGV[0] является первым аргументом введенной команды и может иметь значение up , down , status и т.д. Просто проверьте значение ARGV[0] в вашем Vagrantfile.


Что-то вроде этого подойдет:

system("
    if [ #{ARGV[0]} = 'up' ]; then
        echo 'You are doing vagrant up and can execute your script'
        ./myscript.sh
    fi
")

Vagrant.configure('2') do |config|
  # ...
end
9

Поместите это в верхнюю часть вашего Vagrantfile:

module LocalCommand
    class Config < Vagrant.plugin("2", :config)
        attr_accessor :command
    end

    class Plugin < Vagrant.plugin("2")
        name "local_shell"

        config(:local_shell, :provisioner) do
            Config
        end

        provisioner(:local_shell) do
            Provisioner
        end
    end

    class Provisioner < Vagrant.plugin("2", :provisioner)
        def provision
            result = system "#{config.command}"
        end
    end
end

Затем просто вызовите в своем Vagrantfile вот так:

config.vm.provision "list-files", type: "local_shell", command: "ls"

И через командную строку вот так:

vagrant provision --provision-with list-files

Это своего рода хак, поскольку он выглядит как плагин, но на самом деле это не так (он не будет отображаться, когда вы vagrant plugin list). Я не рекомендую делать это таким образом, за исключением того, что он имеет то преимущество, что не требует установки плагина, поэтому ваш Vagrantfile будет работать на любом компьютере, который поддерживает последнюю версию конфигурации (версия 2 на момент написания этой статьи). Хотя это звучит многообещающе портативно, есть еще и кроссплатформенная проблема самой команды, которую вы выдаете. Вам нужно будет учесть, хотите ли вы, чтобы ваш Vagrantfile был переносимым, но это должно помочь вам начать работу.

4

В соответствии с тем, что @tmatilai сказал об использовании

system('./myscript.sh')

Я нашел это весьма полезным для одноразовых команд, таких как установка бродячих команд или какого-либо провайдера, который может быть не установлен в системе. Я просто избежать его повторного запуска каждый раз , когда я призываю vagrant команды, добавив СЭД для автоматического прокомментируете Vagrantfile

Например:

system('vagrant plugin install vagrant-fabric && (pip install fabric jinja2 || sudo pip install fabric jinja2) && sed -i -e "s/^system/#system/g" Vagrantfile')

И я делаю это первой строкой моего Vagrantfile. Таким образом, он сначала установит плагин vagrant-fabric, fabric и jinja (сначала попробует без sudo для virtualenvs и с sudo если это не удастся), а затем строка прокомментирует себя.

1

На основании ответа @ tmatilai, но обновленного до 2019 года, vagrant-триггеры были объединены в Vagrant. Теперь вы можете сделать что-то вроде этого:

node.trigger.before [:up, :provision] do |trigger|
  trigger.info = "Running ./myscript.sh locally..."
  trigger.run = {path: "./myscript.sh"}
end

Этот блок находится внутри config.vm.define . Дополнительная документация: https://www.vagrantup.com/docs/triggers/

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .