Ejecute el script en la máquina host durante la subida

40

Me gustaría ejecutar un script bash en la máquina host cuando aprovisione vagamente el servidor.

¿Cuál sería el mejor método para lograr esto?

digital
fuente

Respuestas:

29

Al menos dos complementos que deberían ayudar:

Si no le importa que el script se ejecute en (casi) todos los vagrantcomandos, también puede desembolsar (o usar cualquier magia de rubí) en Vagrantfile:

system('./myscript.sh')

Vagrant.configure('2') do |config|
  # ...
end
tmatilai
fuente
2
Los desencadenantes vagos se parecen exactamente a lo que necesito.
digital
¿Dónde encontraste esta función system ()? No puedo encontrar ninguna documentación al respecto en ninguna parte ...
Cristiano Fontes
1
@CristianoFontes, está en el Kernelmódulo, documentado aquí . El Kernelmódulo está incluido en la Objectclase, por lo que sus métodos están disponibles en todos los ámbitos.
tmatilai
1
Estúpido yo. Estaba buscando documentación vagabunda. ¡Gracias!
Cristiano Fontes
26

Solución simple (y completa)

(Digo completa porque la respuesta aceptada no comprueba si el usuario está usando vagabundo. Por lo tanto, el script se ejecuta en cada comando, que no es lo que quiere el OP).

Sin embargo, hay una solución simple para esto.

ARGV[0]es el primer argumento del comando entró y puede ser up, down, status, etc .. Basta comprobar el valor de ARGV[0]en su Vagrantfile.


Algo como esto hará:

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
Mick
fuente
1
Hola, Mick ... Buena respuesta, gracias por ello. Pero no puedo obtener si [# {ARGV [0]} = 'up']; para trabajar en windows. Nunca encuentra el argumento
Cristiano Fontes
1
Esto ejecuta su script antes de que se ejecute cualquier otra cosa, independientemente de su posición en Vagrantfile. Puede que sea suficiente para lo que estás haciendo, pero el complemento de desencadenantes vagos era lo que necesitaba ...
Vigintas Labakojis
3
@CristianoFontes puede hacer la prueba argv en ruby ​​fuera de la llamada del sistema y funcionará en windows y * nix. Lo uso para establecer una variable global ruby ​​que indica que el aprovisionamiento está sucediendo buscando el comando up o provision en la línea de comando: if ARGV [0] = ~ / ^ up | provision $ / i y no ARGV.include? (" --no-provision ") $ provisioning = true else $ provisioning = false end
Ruibarbo
En realidad, esta es una mala práctica según lo aconsejado por Vagrant, debe escribir un complemento para conectar con el comando "arriba", puede especificar cualquiera de: antes, después y alrededor de la ejecución.
SilentICE
1
@Mick es solo de los documentos de Vagrant ( docs.vagrantup.com/v2/plugins/commands.html ). También crea una secuencia de comandos frágil, ya que no puede estar seguro de que, en los casos de llamada, argv [0] está 'activo' en lugar de decir una bandera. Además, si se está convirtiendo en rubí crudo, está rompiendo la encapsulación que se supone que debe proporcionar el marco. Hay mecanismos expuestos para hacer esto correctamente, así que en mi humilde opinión, deberías usarlos siempre que sea posible
SilentICE
9

Pon esto cerca de la parte superior de tu 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

Luego simplemente invoque en su Vagrantfile de esta manera:

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

Y a través de la línea de comando como esta:

vagrant provision --provision-with list-files

Este es un truco, ya que parece un complemento, pero realmente no lo es (no aparecerá cuando lo hagas vagrant plugin list). No recomiendo hacerlo de esta manera, excepto que tiene la ventaja de no necesitar instalar un complemento, por lo que su Vagrantfile funcionará en cualquier máquina que admita la última versión de configuración (versión 2 al momento de escribir esto). Aunque eso suena prometedoramente portátil, también está todo el problema multiplataforma del comando real que está emitiendo. Deberá tener en cuenta si desea que su Vagrantfile sea portátil, pero esto debería ayudarlo a comenzar.

Joel B
fuente
1
Buena respuesta, voy a usar esto para configurar el reenvío de puertos bajos.
poindexter
6

Según la respuesta de @ tmatilai, pero actualizada para 2019, los disparadores vagrant se han fusionado con Vagrant. Entonces ahora puedes hacer algo así:

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

Este bloque va dentro de config.vm.define. Documentación adicional: https://www.vagrantup.com/docs/triggers/

Sean Hood
fuente
Esta es la respuesta más elegante hasta la fecha. Debo agregar que colocar este y otros fragmentos similares dentro config.vm.defineno es un requisito; también se pueden colocar dentro Vagrant.configure("2") do |config| ... end. Como punto final de la nota, en los hosts de Windows, Vagrant con mucho gusto ejecutará scripts de Powershell que también tengan la .ps1extensión.
Ben Johnson
4

En línea con lo que @tmatilai dijo sobre el uso

system('./myscript.sh')

Lo encontré bastante útil para comandos únicos como la instalación de comandos vagos o algún aprovisionador que podría no estar instalado en el sistema. Solo evito que se vuelva a ejecutar cada vez que invoco los vagrantcomandos agregando un sed para auto-comentar el Vagrantfile.

Por ejemplo:

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

Y hago de eso la primera línea de mi Vagrantfile. De esta manera será primero instalar el plugin vagabundo-tela, tela y Jinja (intentará primero sin sudopara virtualenvsy con sudosi eso no funciona) y luego la propia línea comentarios.

kenorb
fuente
Sería más fácil simplemente seleccionar la lista de complementos vagabundos en lugar de descomentar el archivo Vagrant, lo que podría causar problemas a otras personas en su equipo. if [[ $(vagrant plugin list | grep -c vagrant-host-shell) == "0" ]] then vagrant plugin install vagrant-host-shell fi
Jordania
El problema con esto es que se activará en otros comandos, ¿y si se ejecuta vagrant statusantes vagrant up...
Mick