Cerrar todas las máquinas virtuales VirtualBox (vagabundo) en un comando bash fácil de usar (que se puede poner en un archivo bash)

70

Yo uso vagabundo para el desarrollo. Olvidé apagar algunas de las máquinas virtuales. Cuando salgo de mi máquina host, el proceso de apagado de Ubuntu parece bloquearse.

¿Podría haber una manera de escribir un cierre de todos los cuadros vagos con un poco de línea de comandos-fu? Algo como lo siguiente, pero algo que, bueno, funciona.

for f in $HOME/vagrant;
do;
  cd $f
  vagrant halt
done;
Almiar
fuente
No sé vagabundo pero parece estar vinculado a VMWare, no VirtualBox. ¿Estás usando VirtualBox?
terdon
@terdon: Vagrant solo admite Vbox inicialmente. Creo que ahora admiten otro tipo de formatos de VM (entienda VMWare)
Sylvain Pineau
@SylvainPineau ah, está bien. Acabo de echar un vistazo rápido a su página web y vi un enlace de "integración VMWare" y asumí. Gracias por la aclaración.
terdon
1
Echaría un vistazo a este script . La publicación completa del blog está aquí . No probado
Sylvain Pineau
Richard, por favor no edites la respuesta en tu pregunta. Usted es libre de responder su propia pregunta en una respuesta separada. Te di un voto a favor por una buena pregunta.
don.joey

Respuestas:

91

Para un control de secuencias de comandos de máquinas de Virtual Box podemos hacer uso de los comandos VBoxManage :

  • Lista de máquinas en ejecución (devuelve nombre y UUID):

    VBoxManage list runningvms
    
  • Deje de ejecutar máquinas virtuales "hibernando" (recomendado para evitar la pérdida de datos)

    VBoxManage controlvm <name|uuid> savestate
    
  • Apague las máquinas virtuales (no se recomienda porque podemos perder datos en el invitado)

    VBoxManage controlvm <name|uuid> poweroff
    
  • Use ACPI en un sistema operativo invitado compatible con ACPI (preferible poweroffpara el apagado correcto de los invitados)

    VBoxManage controlvm <name|uuid> acpipowerbutton
    

Ver también: Cómo cerrar de manera segura el SO huésped en VirtualBox usando la línea de comando

Actualización desde OP

Basado en esta respuesta correcta seleccionada a continuación, he agregado este script bash " $HOME/bin/stop-vagrant.sh". Así que ahora tengo algo que puede iniciar de forma segura una parada de todas las máquinas virtuales vagabundas que podría haber encendido pero olvidado en una sesión.

vboxmanage list runningvms | sed -r 's/.*\{(.*)\}/\1/' | xargs -L1 -I {} VBoxManage controlvm {} savestate

Comando explicado:

vboxmanage list runningvms | - obtiene una lista de todos los vms en ejecución en VirtualBox

sed -r 's/.*\{(.*)\}/\1/' | - quita la cadena al número de identificación

xargs -L1 -I {} VBoxManage controlvm {} savestate - ejecuta el comando guardar estado en cada cuadro que está abierto.

En xargs

  • -L1 - toma una línea a la vez
  • -I {} - utiliza {} como marcador de posición para el siguiente comando
Takkat
fuente
Whoo Hoo! Dado el consejo anterior, esta línea de comando funciona mágicamente: vboxmanage list runningvms | sed -r 's /.* \ {(. *) \} / \ 1 /' | xargs -L1 -I {} VBoxManage controlvm {} savestate
Rick
1
Tenga en cuenta que la -ropción es exclusiva de GNU Sed.
George V. Reilly
¡La mejor frase mágica que he visto en mucho tiempo! ¡Buen trabajo! : D
tftd
1
En OSX / macOS, deberá usarlo en -Elugar de -r. Es la bandera para usar expresiones regulares extendidas.
JayD3e
22

La otra respuesta es excelente para manejar Virtualbox, pero Vagrant presenta sus propios mecanismos para manejar máquinas virtuales, y como se mencionó en uno de los comentarios, admite más que solo VirtualBox, solo VMWare en este momento, ¡pero quién sabe más adelante!

Esto parece funcionar para mí:

vagrant global-status | awk '/running/{print $1}' | xargs -r -d '\n' -n 1 -- vagrant suspend

Nota:

Esto funciona con las versiones de Vagrant posteriores a 1.6, para versiones anteriores, probablemente debería actualizar, pero si no puede, una de las otras opciones que se centra en Virtualbox puede ser mejor.

ThomasRedstone
fuente
44
esta es obviamente una respuesta mucho más correctora (tm). @Richard debería considerar aceptar este en su lugar
nhed
El global-statuscomando se introdujo en Vagrant 1.6 . Los usuarios de versiones anteriores de Vagrant, en particular aquellos que lo han instalado a través de apt-gety aún pueden estar en 1.4.3, deberán actualizar su instalación de Vagrant antes de poder usar este comando.
Curtis Gibby
1
BSD xargsno soporta -r, por lo tanto, se puede instalar gxargsa través brewy utilizar en su lugar.
kenorb
11

Mi mecanismo para esto:

vagrant global-status | grep virtualbox | cut -c 1-9 | while read line; do echo $line; vagrant halt $line; done;

  • estado global enumera todos los cuadros
  • filtre eso para las líneas que contienen virtualbox(filtra el texto de ayuda, se romperá si está utilizando otro proveedor)
  • Filtre eso para mostrar solo los primeros 9 caracteres (la ID única global)
  • Si bien aún podemos leer una línea desde esa entrada, léala como la variable $ line y luego:
    • Imprime esa línea $
    • ejecutar vagrant halt $linedeteniendo al vagabundo para esa identificación única global

Esto es mejor que el método Virtualbox anterior, porque también ejecutará cualquier mecanismo de apagado configurado vagamente.

Acuario
fuente
3
Este comando también funciona para hosts OS X. Otros fallan debido a diferencias en el manejo de argumentos de línea de comandos entre las versiones de OSX y Linux de sedy awk. ¡Gracias!
Andrew Андрей Листочкин
@ AndrewАндрейЛисточкин Confirmar: funciona bien en OS X 10. Sin embargo, no se ha probado en otros sistemas operativos.
Setevoy
2
El comando anterior intenta detener todos los cuadros, sin importar si se están ejecutando o no, por lo que se tarda mucho tiempo en ejecutarse. Para mí, como solo uso virtualbox, cambié el grep de "virtualbox" a "running", para obtener solo los que se ejecutan.
Alex2php
Esta es una buena respuesta, pero es posible que desee utilizarla en vagrant suspendlugar de vagrant haltguardar el estado y suspenderla para acelerarla.
David Thomas
Es cierto, y si te funciona, es genial. He tenido problemas de cronometraje masivos con máquinas virtuales suspendidas en Virtualbox, por lo que no lo recomendaría.
Acuario
5

En caso de que otras personas lleguen a esta pregunta: para aquellos que usan VirtualBox, ya puede encargarse de esto, solo implica editar un archivo:

# Contents of /etc/default/virtualbox
# ...
# ...
# SHUTDOWN_USERS="foo bar"  
#   check for running VMs of user 'foo' and user 'bar'
#   'all' checks for all active users
# SHUTDOWN=poweroff
# SHUTDOWN=acpibutton
# SHUTDOWN=savestate
#   select one of these shutdown methods for running VMs
#   acpibutton and savestate causes the init script to wait
#   30 seconds for the VMs to shutdown

## My original values
# SHUTDOWN_USERS=""
# SHUTDOWN=poweroff

## My current values
SHUTDOWN_USERS="all"
SHUTDOWN=savestate

Lo bueno es que no es necesario editar / crear ningún cierre de sesión o init.dstript para ejecutar los comandos publicados en las otras respuestas. La desventaja es que esta solución es específica de VirtualBox.

Probado en Ubuntu 14.10 con VirtualBox 4.3.18.

Todo el crédito va a esta publicación .

Armando Pérez Marqués
fuente
5

Combinando algunas de las otras respuestas, esto cerrará todos los cuadros vagabundos de virtualbox en ejecución:

vagrant global-status | awk '/virtualbox running/{ print $1 }' | xargs vagrant halt
Ryan
fuente
¡Esto funcionó para mí!
Dayron Gallardo
3

Yo solo uso vagrant halt. Si lo ejecuta sin más argumentos, detiene todas las máquinas definidas en Vagrantfile.

no hombre
fuente
1

Si está escribiendo scripts para analizar comandos Vagrant, se recomienda analizar la salida amigable para la máquina ( --machine-readable), que es más consistente.

El formato es:

timestamp,target,type,data...

para que pueda importarlo como archivo CSV, ya que está separado por comas.

Con shell, probablemente sea más difícil de analizar, por ejemplo:

for id in $(vagrant global-status --machine-readable | cut -d, -f5 | grep -B3 running | egrep -o "[0-9a-f]{7}"); do
    vagrant suspend $id;
done

Ver: Vagabundo - Salida legible por máquina


Sin embargo, me resulta más fácil analizar la salida estándar, p. Ej.

while read id name provider state path; do
  [ "$state" = "running" ] && vagrant suspend $id;
done < <(vagrant global-status)

Por cierto. Teóricamente, el vagrantcomando debería aceptar una expresión regular para que la lista de máquinas virtuales se suspenda según esta publicación de GH , por ejemplo:

vagrant suspend '*'

pero no funciona y hay un error # 7221 que está pendiente para solucionarlo.


Entradas relacionadas a GitHub:

kenorb
fuente
0

Esto puede o no funcionar para usted ;-) Funciona para mí

vagrant_halt_all.sh

#!/usr/bin/env bash
if [ -z "$1" ]
then
  OPTS=""
else
  # force close if any arg passed
  OPTS="-f"
fi

for i in $(vagrant global-status | grep running | awk '{print $1}'); do 
  DIR=$(vagrant global-status | grep running | awk '{print $5}')
  cd "$DIR";
  OUT=$(vagrant halt);
  echo "attempted to halt $i: $OUT"
done
parques brad
fuente