Arrêt de toutes les machines virtuelles VirtualBox (vagabond) en une seule commande bash facile à utiliser (pouvant être placée dans un fichier bash)

70

J'utilise vagrant pour le développement. J'ai oublié de fermer quelques machines virtuelles. Lorsque je vais me déconnecter de mon ordinateur hôte, le processus d'arrêt d'Ubuntu semble se bloquer.

Pourrait-il y avoir un moyen de script une fermeture de toutes les boîtes vagabondes avec un peu de commandline-fu? Quelque chose comme ce qui suit, mais quelque chose qui fonctionne bien.

for f in $HOME/vagrant;
do;
  cd $f
  vagrant halt
done;
Meule
la source
Je ne connais pas vagabond mais cela semble lié à VMWare, pas à VirtualBox. Utilisez-vous réellement VirtualBox?
terdon
@terdon: Vagrant ne supportait initialement que la Vbox. Je pense qu'ils supportent maintenant d'autres types de formats de VM (comprendre VMWare)
Sylvain Pineau
@ SylvainPineau ah, d'accord. Je viens juste de jeter un coup d’œil sur leur page Web et j’ai vu un lien «Intégration VMWare». Merci pour la clarification.
terdon
1
Je regarderais ce script . L'article complet du blog est ici . Non testé
Sylvain Pineau
Richard, s'il vous plaît, ne modifiez pas la réponse à votre question. Vous êtes libre de répondre à votre propre question dans une réponse séparée. Je vous ai donné un vote positif pour une bonne question.
don.joey

Réponses:

91

Pour un contrôle scriptable des machines Virtual Box, nous pouvons utiliser les commandes VBoxManage :

  • Répertoriez les machines en cours d’exécution (nom et UUID):

    VBoxManage list runningvms
    
  • Arrêtez les machines virtuelles en les "hibernant" (recommandé pour éviter la perte de données)

    VBoxManage controlvm <name|uuid> savestate
    
  • Mise hors tension de machines virtuelles en cours d'exécution (non recommandé car nous risquons de perdre des données dans l'invité)

    VBoxManage controlvm <name|uuid> poweroff
    
  • Utiliser ACPI dans un système d'exploitation invité prenant en compte l'ACPI (préférable à poweroffun arrêt progressif des invités)

    VBoxManage controlvm <name|uuid> acpipowerbutton
    

Voir aussi: Comment arrêter en toute sécurité le système d'exploitation invité dans VirtualBox à l'aide de la ligne de commande

Mise à jour de l'OP

Sur la base de cette réponse correcte sélectionnée ci-dessous, j'ai ajouté ce script bash " $HOME/bin/stop-vagrant.sh". Alors maintenant, j'ai quelque chose qui peut commencer en toute sécurité un arrêt de toutes les machines virtuelles vagabondes que j'ai peut-être allumées mais que j'avais oubliées au cours d'une session.

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

Commande expliquée:

vboxmanage list runningvms | - obtient une liste de tous les vms en cours d'exécution sous VirtualBox

sed -r 's/.*\{(.*)\}/\1/' | - dénude la chaîne jusqu'à son numéro d'identification

xargs -L1 -I {} VBoxManage controlvm {} savestate - exécute la commande save state sur chaque boîte ouverte.

Sur xargs

  • -L1 - prendre une ligne à la fois
  • -I {} - utilise {} comme espace réservé pour la commande suivante
Takkat
la source
Whoo Hoo! Compte tenu des conseils ci-dessus, cette ligne de commande fonctionne de manière magique: vboxmanage list runningvms | sed -r 's / .* \ {(. *) \} / \ 1 /' | xargs -L1 -I {} VBoxManage controlvm {} savestate
Rick
1
Notez que cette -roption est unique à GNU Sed.
George V. Reilly
Meilleur one-liner magique que j'ai vu depuis longtemps! Bon travail! : D
tftd
1
Sous OSX / macOS, vous devrez utiliser à la -Eplace de -r. C'est le drapeau pour utiliser des expressions régulières étendues.
JayD3e
22

L'autre solution est intéressante pour la gestion de Virtualbox, mais Vagrant possède ses propres mécanismes de gestion des machines virtuelles et, comme mentionné dans l'un des commentaires, il prend en charge plus que VirtualBox, uniquement VMWare pour le moment, mais qui sait plus tard!

Cela semble fonctionner pour moi:

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

Remarque:

Cela fonctionne avec les versions de Vagrant après la version 1.6; pour les versions plus anciennes, vous devriez probablement mettre à niveau, mais si vous ne pouvez pas, une des autres options qui se concentrent sur Virtualbox peut être meilleure.

Thomas Redstone
la source
4
c'est évidemment une réponse beaucoup plus correcte (tm). @ Richard devrait envisager d'accepter celui-ci à la place
2014
La global-statuscommande a été introduite dans Vagrant 1.6 . Les utilisateurs de versions plus anciennes de Vagrant, en particulier ceux qui l’ont installé via apt-getet sont peut-être encore sur la version 1.4.3, devront mettre à jour leur installation de Vagrant avant de pouvoir utiliser cette commande.
Curtis Gibby
1
BSD xargsne supporte pas -r, vous pouvez donc installer gxargsvia brewet l'utiliser à la place.
Kenorb
11

Mon mécanisme pour cela:

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

  • état global liste toutes les cases
  • filtre que pour les lignes contenant virtualbox(Filtre le texte d'aide, cassera si vous utilisez un autre fournisseur)
  • Filtrez-le pour n’afficher que les 9 premiers caractères (l’ID unique global)
  • Bien que nous puissions toujours lire une ligne à partir de cette entrée, lisez-la comme la variable $ line puis:
    • Imprimer cette ligne $
    • courir vagrant halt $linearrêter le vagabond pour cet identifiant unique global

C'est mieux que la méthode Virtualbox ci-dessus, car elle exécutera également tous les mécanismes d'arrêt configurés de manière vagabonde.

Aquarion
la source
3
Cette commande fonctionne également pour les hôtes OS X. D'autres échouent en raison de différences dans la gestion des arguments de ligne de commande entre les versions OSX et Linux de sedet awk. Merci!
Andrew Андрей Листочкин le
@ AndrewАндрейисточкин Confirm - fonctionne sous OS X 10. Ne teste pas sur d'autres OS bien que.
Setevoy
2
La commande ci-dessus tente d’arrêter toutes les boîtes, qu’elles soient ou non en cours d’exécution, ce qui prend beaucoup de temps. Pour moi, comme je n'utilise que virtualbox, j'ai changé le "virtualbox" de grep en "en cours d'exécution", pour ne récupérer que ceux qui fonctionnent.
Alex2php
C'est une bonne réponse, mais vous voudrez peut-être utiliser vagrant suspendplutôt que de vagrant haltsauvegarder l'état et de le suspendre plus rapidement.
David Thomas
C'est vrai, et si cela fonctionne pour vous, tant mieux. J'ai eu de gros problèmes de chronométrage avec des machines virtuelles suspendues sous Virtualbox, donc je ne le recommanderais pas.
Aquarion
5

Au cas où d'autres personnes en arriveraient à cette question: pour ceux qui utilisent VirtualBox, cela peut déjà résoudre le problème, il suffit d'éditer un fichier:

# 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

L'avantage est qu'il n'est pas nécessaire de modifier / créer une déconnexion ou d' init.deffacer pour exécuter les commandes publiées dans les autres réponses. L'inconvénient est que cette solution est spécifique à VirtualBox.

Testé sur Ubuntu 14.10 avec VirtualBox 4.3.18.

Tout le crédit va à ce post .

Armando Pérez Marqués
la source
5

En combinant certaines des autres réponses, toutes les boîtes virtuelles virtualbox en cours d'exécution seront fermées:

vagrant global-status | awk '/virtualbox running/{ print $1 }' | xargs vagrant halt
Ryan
la source
Cela a fonctionné pour moi!
Dayron Gallardo le
3

Je viens d'utiliser vagrant halt. Si vous l'exécutez sans autre argument, il arrête toutes les machines définies dans le fichier Vagrantfile.

pas d'hommes
la source
1

Si vous écrivez des scripts pour analyser les commandes Vagrant, il est conseillé d’analyser la sortie conviviale pour les machines ( --machine-readable), qui est plus cohérente.

Le format est:

timestamp,target,type,data...

vous pouvez donc l'importer en tant que fichier CSV, car il est séparé par des virgules.

Avec shell, c'est probablement plus difficile à analyser, par exemple:

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

Voir: Vagant - Sortie lisible par machine


Cependant, je trouve plus facile d'analyser la sortie standard, par exemple

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

Btw. Théoriquement, la vagrantcommande devrait accepter une expression régulière pour la liste des machines virtuelles à suspendre conformément à cette publication GH , par exemple:

vagrant suspend '*'

mais cela ne fonctionne pas et il y a un bogue # 7221 qui est en attente afin de le réparer.


Billets GitHub associés:

Kenorb
la source
0

Cela peut ou peut ne pas fonctionner pour vous ;-) Fonctionne pour moi

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
Brad Park
la source