Virtualbox Windows ordnungsgemäßes Herunterfahren von Gästen beim Herunterfahren des Hosts

19

Ich versuche eine Lösung zu finden, um alle Gast-VMs, die unter VirtualBox Windows ausgeführt werden, ordnungsgemäß herunterzufahren, wenn der Host-Computer heruntergefahren oder neu gestartet wird.

Es scheint, dass die sicherste Option darin besteht, den Befehl "save state" auszulösen, wenn der Host heruntergefahren wird. Es ist jedoch nicht klar, ob der Host lange genug warten wird, bis die VMs den Speichervorgang abgeschlossen und ausgeschaltet haben.

Hat jemand eine robuste Lösung für dieses (scheinbar grundlegende) Problem?

Matt Jenkins
quelle
Installieren Sie die Gastzusätze? Bietet das nicht die erforderliche Funktionalität?
Kanadier Luke REINSTATE MONICA
@CanadianLuke Tut es nicht. :)
Matt Jenkins

Antworten:

6

Ich hatte ein ähnliches Problem und löste es, indem ich VirtualBox als Dienst ausführte:

http://vboxvmservice.sourceforge.net/

Mit VBoxVMService können Sie festlegen, wie der Computer heruntergefahren (Status speichern, ausschalten) und gestartet werden soll. Da es als Dienst ausgeführt wird, wartet Windows während des Herunterfahrens des Systems automatisch darauf, dass es heruntergefahren wird.

Bill Westrup
quelle
Der Einrichtungsprozess ist unter Windows 10 nicht so automatisch. Ich muss mich auf die Fehlersuche beziehen, um zu sehen, was nicht stimmt. Nach der korrekten Konfiguration macht diese Software genau das, was ich brauche. Vielen Dank für Ihre großartige Arbeit.
iuradz
3

Leider scheint dies für VMs, die über die VirtualBox-GUI gestartet wurden, nicht möglich zu sein. Auch wenn die GUI das Host-Shutdown-Ereignis abfängt und reagiert, wird der VirtualBox-Dienst beendet: https://forums.virtualbox.org/viewtopic.php?p=278668#p278668

Wenn Sie keine grafische Konsole benötigen, sind VBoxHeadlessTray oder VBoxVMService möglicherweise die richtige Wahl. Beide unterstützen das automatische Speichern und Fortsetzen beim Herunterfahren und Neustarten des Windows-Hosts.

VirtualBox 5.0 führt einen Startmodus mit abnehmbarer Benutzeroberfläche ein . Dieser Modus startet eine Headless-VM mit einem separaten UI-Prozess. Die Grafikleistung leidet jedoch, und die 3D-Beschleunigung wird noch nicht unterstützt. Aber möglicherweise kann dies in Zukunft mit VBoxHeadlessTray kombiniert werden (VBoxHeadlessTray unterstützt noch nicht 5.0.) Links zum VBoxHeadlessTray-GitHub-Repository und zur entsprechenden GitHub-Pull-Anfrage zum Hinzufügen von VirtualBox 5-Unterstützung .

Bearbeiten: VBoxVmService unterstützt den neuen abnehmbaren Modus ab Version 5.0 ebenfalls nicht. Bisher nur kopflos . Dafür habe ich eine Feature-Anfrage hinzugefügt .

Leo B
quelle
Da ich nicht mehr als zwei Links pro Post portieren darf, sind hier die Links zu VBoxHeadlessTray und zur entsprechenden GitHub-Pull-Anfrage für das Hinzufügen von VirtualBox 5-Unterstützung.
Leo B
Die im Thread beschriebenen Probleme treten nicht auf. Siehe meine Antwort zu diesem Thema. Ich kann den Windows-Host herunterfahren und gehen. Das Herunterfahren wird blockiert, bis alle meine VMs geschlossen sind, und ich habe die Standardaktion geändert, um ein sauberes Herunterfahren oder einen Speicherstatus durchzuführen.
Kris Bahnsen
2

Ich habe 3 Batch-Skripte, die ich anstelle der Power-Buttons des Startmenüs verwende.

do_shutdown.bat (Herunterfahren des PCs mit einer Wartezeit von 10 Sekunden, um dem VM nicht 10 Sekunden Zeit zum Speichern zu geben, sondern um es mir zu ermöglichen, das Herunterfahren innerhalb von 10 Sekunden abzubrechen. Der Countdown beginnt, nachdem die VMs heruntergefahren wurden.)

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

do_reboot.bat (startet sofort nach dem Herunterfahren des virtuellen Computers neu)

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

do_cancel.bat (Ermöglicht mir, das Herunterfahren des PCs innerhalb der Wartezeit von 10 Sekunden abzubrechen. Anschließend werden die VMs neu gestartet, da sie mit do_shutdown.bat heruntergefahren wurden.)

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

Anstelle von können savestateSie auch eines der folgenden verwenden

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)
Daniel F
quelle
1
Danke, das ist interessant. Leider gibt es auch andere nicht manuelle Szenarien zum Herunterfahren / Neustarten, die ich behandeln muss. Beispielsweise durch Windows Update geplante Neustarts oder Ereignisse bei niedrigem Batteriestand.
Matt Jenkins
1
Oh ok. Es gibt auch den Gruppenrichtlinien-Editor mit dem Abschnitt "Scripts (Startup / Shutdown)" lifehacker.com/… Ich verwende diesen für einen sehr kurzen Befehl zum Herunterfahren (ein Curl-Aufruf), damit ich nicht weiß, wie er sich verhält auf Skripten, die eine Weile dauern.
Daniel F
2

Tut mir leid, dass ich zu spät zur Party komme. Es gibt eine genaue Antwort darauf, obwohl es einige Kommandozeilen-FOO erfordert. Weitere Informationen finden Sie in diesem Thread-Beitrag: https://forums.virtualbox.org/viewtopic.php?f=6&t=53684#p285540

Der gesuchte Befehl lautet:

"C: \ Programme \ Oracle \ VirtualBox \ VBoxManage.exe" setextradata "VM NAME" GUI / DefaultCloseAction Shutdown

Das verwende ich auf mehreren VMs, schließe das Fenster und es startet automatisch ein sicheres Herunterfahren. Fahren Sie Windows herunter und warten Sie beim Versuch, alles zu schließen, bis diese Prozesse abgeschlossen sind.

Kris Bahnsen
quelle
1

Ich hatte eine ähnliche Frage und fand diese Seite. Ich möchte VirtualBox nicht als Dienst ausführen, da ich viele VMs zum Testen habe und normalerweise andere zur Ausführung in der VirtualBox-Benutzeroberfläche auswähle. Wenn ich meinen Computer herunterfahre, ist es ärgerlich, den Status jeder VM manuell zu speichern. Die Verwendung von Skripten zum Speichern aller laufenden VMs scheint in diesem Fall eine praktische Lösung zu sein. Um die Antwort von Daniel F zu verallgemeinern, habe ich diese Skripte geschrieben, die automatisch den Status aller laufenden VMs speichern, ohne sie explizit zu benennen.

saveRunningVMs.bat für 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 für 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
Karl Wolfram
quelle
0

Ich habe ein Python-Skript erstellt, mit dem alle ausgeführten VirtualBox-VMs angehalten werden. Anschließend habe ich das System so eingerichtet, dass das Skript beim Abmelden als geplante Aufgabe ausgeführt wird.

Ich weiß nicht, wie zuverlässig diese Methode genau ist. Wie andere angemerkt haben, gibt es Einschränkungen, wie lange das System auf den Abschluss einer Winlogon 7002-Task warten soll. Aber ich persönlich hatte kein Problem damit, nutzbare Speicherzustände zu liefern, selbst wenn mehrere VMs mit mehr als 4 GB RAM ausgeführt werden.

Hier sind die Schritte zum Einrichten:

  1. Laden Sie Python 2.7.x von python.org herunter und installieren Sie es
  2. Erstellen Sie die Python-Skriptdatei irgendwo auf Ihrem System mit Notepad oder einem anderen Nur-Text-Editor (siehe unten).
  3. Öffnen Sie den Taskplaner
  4. Wählen Sie Aktion -> Grundlegende Aufgabe erstellen ... und erstellen Sie mit dem Assistenten eine Aufgabe mit den folgenden Einstellungen
    • Ein Name Ihrer Wahl
    • Starten Sie die Aufgabe, wenn ein bestimmtes Ereignis protokolliert wird
    • Protokoll: System
    • Quelle: Winlogon
    • Ereignisid: 7002
    • Starten Sie ein Programm
    • Neben Programm / Skript , geben Sie den vollständigen Pfad zu Ihrem python.exe, zum Beispielc:\Python27\python.exe
    • Geben Sie neben Argumente hinzufügen den vollständigen Pfad ein, in dem Sie die Python-Skriptdatei abgelegt haben, z. B. habe ich meine in einem Unterordner meines Dokumentenordners abgelegtC:\Users\rakslice\Documents\vboxsuspend\vboxsuspend.py
    • Wählen Sie Finish.

Jetzt sollten VirtualBox-VMs beim Abmelden / Neustarten / Herunterfahren angehalten werden.

Das Python-Skript zum Herunterfahren ist unten:

# 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 __name__ == "__main__":
    main()
Rakslice
quelle
1
Der Vorschlag anderer, ein Stapelskript zu verwenden, das Sie manuell ausführen können, um die Sicherheit zu gewährleisten und dann herunterzufahren, ist großartig, wenn das zu Ihrem Anwendungsfall passt. Aber was ich wirklich will, ist ein automatischer Neustart von Windows Update, nachdem eine VM, mit der ich gearbeitet habe, in den letzten zwei Tagen nacheinander durch Windows Update-Neustarts über Nacht hart ausgeschaltet wurde ...
rakslice