Schließen Sie die Virtualbox-Maschine beim Neustart des Hosts sicher

8

Ich verwende Windows 7 in Virtualbox unter Ubuntu 11.10. Alles funktioniert gut. Ich führe es beim Start aus, habe aber ein Problem mit dem Neustart.

Wenn ich tippe, wird sudo reboot nowder Status des virtuellen Windows 7 nicht gespeichert. Nach dem Neustart startet die Virtualbox, aber anstelle von Windows wird das Absturz-Startmenü von Windows 7 angezeigt, und Windows wird erneut gestartet.

Gibt es eine Option, mit der Ubuntu ein Signal an die virtuelle Box senden könnte, um die Instanz vor dem Neustart des Hosts sicher zu schließen?

Takeshin
quelle

Antworten:

6

Falls Sie wirklich herunterfahren müssen, während eine virtuelle Maschine in Virtual Box ausgeführt wird, können Sie ein eigenes Skript für ein manuelles Herunterfahren definieren, in dem Sie einen Befehl zum Speichern des Maschinenstatus eingeben, bevor der Herunterfahrenvorgang beginnt:

VBoxManage controlvm <name> savestate # <name> is the name of your VM
gnome-session-quit --power-off # this example displays the power-off dialog for >11.10

Alternativ können Sie auch ein Skript generieren, das beim Herunterfahren immer ausgeführt wird .

Takkat
quelle
4

Wenn Sie sudo rebootProgramme verwenden, wird das Kill-Signal automatisch beendet, ohne dass eine Anwendung Zeit hat, um auf eine solche Situation zu reagieren. Dies ist kein Fehler, es hat immer auf die gleiche Weise funktioniert und das ist das erwartete Verhalten.

Es gibt eine ähnliche Frage , wo man sehen kann , welche Befehle gegeben werden , wenn Sie die Taste shutdown, reboot, suspend, etc Taste auf das Benutzermenü, sollte eine solche Lösung fragen Sie , was zu tun ist, wenn versucht , ein Fenster mit einer laufenden Anwendung und deren vorzuziehen zu schließen (in Ihr Fall) zum sudo shutdownAnsatz. Guck mal

Bruno Pereira
quelle
Ist der Neustart in letzter Zeit höflicher geworden? In der Manpage für reboot12.10 heißt es: "Wenn dieses Tool mit --force oder in Runlevel 0 oder 6 aufgerufen wird, ruft es den Systemaufruf reboot (2) selbst auf und startet das System direkt neu. Andernfalls wird einfach das Tool shutdown (8) mit aufgerufen." die entsprechenden Argumente. "; und auf der Manpage für shutdownheißt es: "Nach Ablauf der ZEIT sendet das Herunterfahren eine Anforderung an den init (8) -Dämon, um das System auf den entsprechenden Runlevel herunterzufahren."
Echristopherson
4

Ich würde einen differenzierteren Ansatz empfehlen, der einen Startjob, ein Start- und Stoppskript umfasst. Als Beispiel verwende ich Windows XP, da in meinem Home-Verzeichnis Tombert verwendet werden kann ... was Sie entsprechend ändern sollten. Es hat den Vorteil, dass alles, was Sie tun (Neustart, Herunterfahren, Drücken des Netzschalters), Ihre virtuelle Maschine gut handhabt .

Zuerst den Startjob in /etc/init/winxpvm.conf:

description "WinXP VirtualBox job"
author "Thomas Perschak"

## 0: system halt
## 1: single-user mode
## 2: graphical multi-user plus networking
## 6: system reboot
start on started rc RUNLEVEL=[2]
stop on starting rc RUNLEVEL=[!2]

## upstart config
kill timeout 120
kill signal SIGCONT
nice -10

## start WinXP VirtualBox
exec /home/tombert/scripts/winxpvm-start.sh

## stop WinXP VirtualBox
pre-stop exec /home/tombert/scripts/winxpvm-stop.sh

Der Upstart-Job startet die virtuelle Maschine in Runlevel 2 (im grafischen Modus) und erhöht in meinem Fall die Priorität mit nice. Um die virtuelle Maschine ordnungsgemäß herunterzufahren, muss ich die Upstart-Beendigung mithilfe der kill signal SIGCONTAnweisung "deaktivieren" . Dadurch wird die virtuelle Maschine zunächst ausgeführt (wobei die Standardeinstellung vermieden wird SIGTERM). Nach 120 Sekunden SIGKILLwird das trotzdem gesendet. Stattdessen führe ich das winxpvm-stop.shSkript aus.

Randnotiz 1: Die Strophen start on started runlevel [2]und stop on starting runlevel [!2]funktionieren nicht. Man muss den Job ausdrücklich erwähnen rc.

Randnotiz 2: Was auch aus dem Upstart-Handbuch verwirrend ist: Die kill signalZeilengruppe gibt das Signal an, das nach 5 Sekunden gesendet wird. In diesem Beispiel habe ich es von SIGTERM(Standard) auf SIGCONT gesetzt - aber das 5-Sekunden-Timeout konnte ich nicht ändern. Die kill timeoutZeilengruppe gibt das Zeitlimit an, nach dem das SIGKILLgesendet wird - welches Signal man nicht ändern kann. Eine Verbesserung wäre daher die Definition neuer Strophen term signalund term timeout.

Hier das Startskript winxpvm-start.sh:

#! /bin/bash -e

function dostart()
{
    echo -n "Running WinXP ... "
    vboxheadless --startvm WinXP
    echo "now closed"
}
export -f dostart

if [ $(whoami) != "tombert" ]; then
    su -c dostart tombert
else
    dostart
fi

Da alle Einstellungen usw. im Benutzermodus vorgenommen werden (da mein Login Tombert ist ), ändere ich das Konto in Tombert , auch wenn es als Root ausgeführt wird . Der Benutzer könnte natürlich in der Upstart-Konfiguration geändert werden, aber diese Lösung lässt mir die Möglichkeit, die virtuelle Maschine "von Hand" über die Konsole zu starten / zu stoppen.

Je interessanter das Shutdown-Skript in winxpvm-stop.sh ist:

#! /bin/bash

function dostop()
{
    ## check if WinXP is running
    vboxmanage showvminfo WinXP --machinereadable | grep -q 'VMState="running"' &> /dev/null
    if [ $? -ne 0 ]; then
        echo "WinXP not running"
        exit
    fi
    ## try gracefully shutdown
    echo -n "Shutting down WinXP ... "
    #vboxmanage controlvm WinXP acpipowerbutton
    vboxmanage guestcontrol WinXP execute --image "%SystemRoot%\system32\shutdown.exe" --username tombert --password <mypassword> --wait-exit -- "-s" "-f" "-t" "0" &> /dev/null
    ## check vm status
    INDEX=60
    while [ $INDEX -gt 0 ]; do
        echo -n "$INDEX "
        vboxmanage showvminfo WinXP --machinereadable | grep -q 'VMState="running"' &> /dev/null
        if [ $? -ne 0 ]; then
            echo "gracefully done"
            break
        fi
        sleep 1
        let INDEX+=-1
    done
    ## close forcefully
    if [ $INDEX -eq 0 ]; then
        vboxmanage controlvm WinXP poweroff &> /dev/null
        echo "forcefully done"
    fi
}
export -f dostop

if [ $(whoami) != "tombert" ]; then
    su -c dostop tombert
else
    dostop
fi

Zuerst mache ich dasselbe wie im Startskript - ich ändere den Benutzer von root auf mein Konto tombert . Schauen wir uns nun die Funktion an dostop. Zuerst überprüfe ich, ob die virtuelle Maschine überhaupt läuft. Dann versuche ich "sanft" herunterzufahren, indem ich ein Herunterfahren direkt an WinXP mit sende guestcontrol. Hier müssen Sie die Anmeldeinformationen für das WinXP-Konto angeben , in meinem Fall Tombert und ein Kennwort. Das Windows shutdownschließt ordnungsgemäß alle Anwendungen und schaltet das Betriebssystem (normalerweise) aus. Lassen Sie uns dann den Status der virtuellen Maschine kontinuierlich mit überprüfen showvminfo. Wenn Sie dies mindestens 60 Mal mit einer Zeitüberschreitung von 1 Sekunde tun (tun Sie, was Sie für angemessen halten), sollte die virtuelle Maschine genügend Zeit haben, um ordnungsgemäß herunterzufahren. Beachten Sie, dass der Anruf anshowvminfodauert auch etwas weniger als eine Sekunde (zumindest auf meinem Computer), so dass es in meinem Fall ~ 120 Sekunden gibt. Wenn alles bremst, können wir mit der poweroffAnweisung gewaltsam herunterfahren .

Sie sollten auch die sehen acpipowerbutton, aber nicht verwendet. Dies liegt daran, dass es nicht zuverlässig funktioniert. Wenn Sie bei Windows angemeldet sind oder noch schlimmer, mehrere Benutzer, zeigt Windows ein Bestätigungsdialogfeld zum Herunterfahren an, das das Herunterfahren des Systems verhindert. Dies ist auch der Grund, warum die acpibuttonin der /etc/default/virtualboxnicht 100% zuverlässig funktionieren. Außerdem poweroffwird die virtuelle Maschine gewaltsam heruntergefahren - genau wie bei einem langen Netzschalter. Daher ist es am besten, dies auf leer zu setzen:

Auszug aus / 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
SHUTDOWN_USERS=""
SHUTDOWN=""

Um es perfekt zu machen, möchten Sie möglicherweise das Verhalten des Netzschalters ändern:

Auszug aus /etc/acpi/powerbtn.sh:

#!/bin/sh
# /etc/acpi/powerbtn.sh
# Initiates a shutdown when the power putton has been
# pressed.

# @backup
# plain shutdown
/sbin/shutdown -h now "Power button pressed"

# fini
exit 0
...
...

Es gibt noch einen kleinen Nachteil. Wenn die virtuelle Maschine noch bootet und der Gaststeuerungsdienst nicht aktiv ist (in der virtuellen Maschine), wird der Befehl zum Herunterfahren nicht empfangen. Ein seltener Fall ... aber denken Sie darüber nach.

Das ist es, hoffe es hilft.

Tombert
quelle
Funktioniert wie ein Zauber (Windows XP-Gast), außer dass es VERR_INVALID_PARAMETERauf der Host-Seite einen zu werfen scheint, wenn ich über RDC als der im Skript angegebene Benutzer angemeldet bin und der Gast anschließend weiter ausgeführt wird.
Echristopherson
Ich habe es sowohl mit nativem RDC als auch mit RDC über VirtualBox versucht. Kein solcher Fehler. Wahrscheinlich im Zusammenhang mit virtualbox.org/ticket/8197
Tombert
2

Befolgen Sie diese Antwort, um Ihre Systemrichtlinie für den Neustart zu ändern

Sie können dies nicht rationalisieren reboot. AFAIK- init.dSkripte funktionieren nicht, da sie zu lange dauern. Sie können den Befehl jedoch folgendermaßen ausführen:

VBoxManage controlvm <vm> savestate&&reboot

Wo <vm>ist der Name der virtuellen Maschine?

Amith KK
quelle
1

Sie können eine Anforderung zum Herunterfahren an die virtuelle Maschine senden mit:

VBoxManage controlvm <vm_name> acpipowerbutton

Wenn Sie dies jedoch in einem Init-Skript tun, sollte das Skript erst beendet werden, wenn das Herunterfahren abgeschlossen ist. Möglicherweise können wir dies erkennen, indem wir die Laufwerksdatei (.vdi) der VM mit lsofoder fuserin einer Schleife abfragen . Oder als billige Problemumgehung sleep 20kann genügen.

Folgendes verwende ich derzeit im Close-Block meines Init-Skripts:

# This always returns 0, even if an error is displayed!
su - "$DAEMONUSER" VBoxManage controlvm "$VMNAME" acpipowerbutton

# Wait until the disk file is no longer open...
for attempt in `seq 1 20`
do
    fuser "$VMDISKIMAGE" >/dev/null 2>&1 || break
    sleep 2
done

return 0    # A better script would return success/fail

Nahe dem Anfang der Datei, die ich definiert habe:

VMDISKIMAGE="/home/$DAEMONUSER/VirtualBox VMs/$VMNAME/$VMNAME.vdi"

Dadurch wird die VirtualBox-App möglicherweise nicht geschlossen, es wird jedoch darauf gewartet, dass die VM vollständig heruntergefahren wird. Es funktioniert auch nicht, wenn die virtuelle Maschine noch hochgefahren wird (viele Betriebssysteme ignorieren in dieser Phase die Ausschalttaste) oder wenn Sie ein altes System ohne ACPI-Unterstützung emulieren.

joeytwiddle
quelle