web-dev-qa-db-fra.com

Virtualbox Windows, arrêt gracieux des invités à la fermeture de l'hôte

J'essaie de trouver une solution pour arrêter en douceur toutes les machines virtuelles invitées s'exécutant sous Windows VirtualBox lorsque l'ordinateur hôte est arrêté ou redémarré.

Il semble que l'option la plus sûre consisterait à déclencher la commande "save state" lorsque l'hôte commencera à fermer, mais il n'est pas clair si l'hôte attendra assez longtemps pour que les ordinateurs virtuels terminent l'enregistrement et se mettent hors tension.

Quelqu'un at-il une solution solide à ce problème (apparemment fondamental)?

18
Matt Jenkins

J'ai eu un problème similaire et je l'ai résolu en exécutant VirtualBox en tant que service:

http://vboxvmservice.sourceforge.net/

Avec VBoxVMService, vous pouvez choisir le mode d’arrêt de la machine (état d’enregistrement, mise hors tension) et son démarrage. Comme il fonctionne en tant que service, Windows attendra automatiquement son arrêt lors du processus d'arrêt du système.

6
Bill Westrup

Malheureusement, cela ne semble pas possible pour les machines virtuelles démarrées via l'interface graphique de VirtualBox. Même si l'interface graphique peut intercepter l'événement d'arrêt de l'hôte et réagir, le service VirtualBox est arrêté: https://forums.virtualbox.org/viewtopic.php?p=278668#p278668

Si vous n'avez pas besoin d'une console graphique, vous pouvez utiliser VBoxHeadlessTray ou VBoxVMService. Les deux prennent en charge l'enregistrement et la reprise automatiques lors de l'arrêt et du redémarrage de Windows Host.

VirtualBox 5.0 introduit un mode "Interface utilisateur détachable" start. Ce mode démarre un VM sans tête avec un processus d'interface utilisateur distinct. Les performances graphiques en pâtissent cependant et l'accélération 3D n'est pas encore prise en charge. Mais peut-être que cela pourra être combiné à l'avenir avec VBoxHeadlessTray (VBoxHeadlessTray ne supporte pas encore la version 5.0.) Liens vers VBoxHeadlessTray GitHub repository et vers la demande d'extraction correspondante GitHub pour l'ajout de VirtualBox 5 support .

Edit: VBoxVmService également ne supporte pas le nouveau mode détachable à partir de la version 5.0. Seulement sans tête jusqu'à présent. J'ai ajouté une fonctionnalité demande pour cela.

3
Leo B

Désolé je suis en retard à la fête. Il y a une réponse exacte à cela, bien que cela nécessite un certain commandline-foo. Voir ce fil de discussion pour plus d'informations: https://forums.virtualbox.org/viewtopic.php?f=6&t=53684#p285540

La commande que vous recherchez est:

"C:\Program Files\Oracle\VirtualBox\VBoxManage.exe" setextradata "GUI VM"/arrêt par défaut de CloseCloseAction

C’est ce que j’utilise sur plusieurs ordinateurs virtuels, fermez la fenêtre et cela déclenche automatiquement un arrêt sécurisé. Arrêtez Windows et dans sa tentative de tout fermer, il attendra que ces processus soient terminés.

2
Kris Bahnsen

J'ai eu une question similaire et trouvé cette page. Je ne souhaite pas utiliser VirtualBox en tant que service, car j'ai beaucoup de machines virtuelles à tester et je choisis généralement différentes machines à exécuter dans l'interface utilisateur de VirtualBox. Lorsque j'arrête mon ordinateur, il est ennuyeux de sauvegarder manuellement l'état de chaque machine virtuelle. L'utilisation de scripts pour enregistrer toutes les machines virtuelles en cours d'exécution semble être une solution pratique dans ce cas. Pour donner une réponse plus générale à Daniel F, j’ai écrit ces scripts qui enregistrent automatiquement l’état de toutes les machines virtuelles en cours d’exécution sans les nommer explicitement.

saveRunningVMs.bat pour Windows:

set VBoxManageEXE="%ProgramFiles%\Oracle\VirtualBox\VBoxManage.exe"
set ListRunningVMS=%VboxManageEXE% list runningvms
for /f tokens^=2^,4^ delims^=^" %%p in ('%ListRunningVMS%') do %VBoxManageEXE% controlvm %%p savestate

echo all vms saved, you can shutdown now.

rem shutdown /s /t 10

saveRunningVMs.sh pour Linux:

#!/bin/bash
vboxmanage list runningvms | while read line; do
  #echo "VBoxManage controlvm $uuid savestate;"
  echo $line
  if [[ $line =~ \{(.*)\} ]]
  then
    vboxmanage controlvm ${BASH_REMATCH[1]} savestate
  fi
done
1
Karl Wolfram

J'ai 3 scripts batch que j'utilise à la place des boutons d'alimentation du menu Démarrer.

do_shutdown.bat (ordinateur à l'arrêt avec une période d'attente de 10 secondes, pour ne pas laisser à la machine virtuelle le temps nécessaire pour la sauvegarde, mais pour me permettre d'annuler l'arrêt dans les 10 secondes. Le compte à rebours commence après l’arrêt des machines virtuelles)

"C:\VirtualBox\VBoxManage.exe" controlvm "Ubuntu Server" savestate
"C:\VirtualBox\VBoxManage.exe" controlvm "Ubuntu Minimal" savestate
shutdown /s /t 10

do_reboot.bat (redémarre immédiatement après la fermeture de la machine virtuelle)

"C:\VirtualBox\VBoxManage.exe" controlvm "Ubuntu Server" savestate
"C:\VirtualBox\VBoxManage.exe" controlvm "Ubuntu Minimal" savestate
shutdown /r /t 0

do_cancel.bat (me permet d'annuler l'arrêt de l'ordinateur dans le délai d'attente de 10 secondes. Il redémarre ensuite à nouveau les machines virtuelles, car elles ont été fermées avec le do_shutdown.bat)

shutdown /a
C:\VirtualBox\VBoxManage.exe startvm "Ubuntu Minimal" --type headless
C:\VirtualBox\VBoxManage.exe startvm "Ubuntu Server" --type headless

Au lieu de savestate, vous pouvez également utiliser l’un des logiciels suivants:

poweroff        - pulls the plug
                  (probably not a good idea...)

acpipowerbutton - presses the power off button for a clean shutdown
                  ("The system is going down for power off NOW!" to all consoles)

acpisleepbutton - tells the os to go to sleep
                  (probably just as bad as poweroff)
1
Daniel F

J'ai créé un script python qui suspendreait toutes les machines virtuelles VirtualBox en cours d'exécution, puis configurer le système pour qu'il exécute le script à la déconnexion en tant que tâche planifiée.

Je ne sais pas à quel point cette méthode est fiable. Comme d'autres l'ont noté , le temps d'attente du système avant la fin d'une tâche Winlogon 7002 est limité. Mais personnellement, je n’ai eu aucun problème à ce qu’il fournisse des états de sauvegarde utilisables, même avec plusieurs ordinateurs virtuels en cours d’exécution, sur plus de 4 Go de VM RAM globale.

Voici les étapes pour le configurer:

  1. Téléchargez et installez Python 2.7.x à partir de python.org
  2. Créez le fichier de script Python quelque part sur votre système à l'aide de Notepad ou de tout autre éditeur de texte (voir ci-dessous).
  3. Ouvrir le planificateur de tâches
  4. Choisissez Action -> Créer une tâche élémentaire ... et utilisez l'assistant pour créer une tâche avec les paramètres suivants
    • Un nom de votre choix
    • Démarrer la tâche lorsqu'un événement spécifique est enregistré
    • Journal: système
    • Source: Winlogon
    • ID d'événement: 7002
    • Commencer un programme
    • En regard de Programme/Script , entrez le chemin complet de votre python.exe, par exemple c:\Python27\python.exe.
    • À côté de Ajouter des arguments , entrez le chemin complet dans lequel vous placez le fichier de script python. Par exemple, je mets le mien dans un sous-dossier de mon dossier de documents. Il s'agit donc de C:\Users\rakslice\Documents\vboxsuspend\vboxsuspend.py
    • Choisissez Terminer.

Désormais, les machines virtuelles VirtualBox doivent être suspendues lors de la déconnexion/du redémarrage/de l'arrêt.

Le script python pour effectuer la fermeture est ci-dessous:

# A script to suspend all running VirtualBox VMs

import os

import subprocess

import sys


class VM(object):
    def __init__(self, name, uuid):
        self.name = name
        self.uuid = uuid

    def __repr__(self):
        return "VM(%r,%r)" % (self.name, self.uuid)


class VBoxRunner(object):
    def __init__(self):
        program_files = os.environ["ProgramW6432"]
        vbox_dir = os.path.join(program_files, "Oracle", "VirtualBox")
        self.vboxmanage_filename = os.path.join(vbox_dir, "VBoxManage.exe")

    def vbox_run(self, *args):
        subprocess.check_call([self.vboxmanage_filename] + list(args))

    def vbox_run_output(self, *args):
        return subprocess.check_output([self.vboxmanage_filename] + list(args))

    def list(self, running=True):
        if running:
            list_cmd = "runningvms"
        else:
            list_cmd = "vms"

        return [self.parse_vm_list_entry(x) for x in self.vbox_run_output("list", list_cmd).strip().split("\n")]

    def suspend_all(self):
        success = True
        stopped_some_vms = False
        vms = self.list(running=True)
        for vm in vms:
            if vm is None:
                continue
            # noinspection PyBroadException
            try:
                self.suspend_vm(vm)
            except:
                success = False
            else:
                stopped_some_vms = True
        if not stopped_some_vms:
            self.message("No running vms")
        return success

    @staticmethod
    def parse_vm_list_entry(x):
        """:type x: str"""
        if not x.startswith('"'):
            return None
        end_pos = x.find('"', 1)
        if end_pos == -1:
            return None
        name = x[1:end_pos]
        assert x[end_pos + 1: end_pos + 3] == " {"
        assert x.endswith("}")
        uuid = x[end_pos + 2:]

        return VM(name, uuid)

    @staticmethod
    def message(msg):
        print >>sys.stderr, msg

    def suspend_vm(self, vm):
        assert isinstance(vm, VM)
        self.vbox_run("controlvm", vm.uuid, "savestate")


def main():
    vr = VBoxRunner()
    success = vr.suspend_all()
    if not success:
        sys.exit(1)


if __== "__main__":
    main()
0
rakslice