Fermez la machine virtualbox en toute sécurité au redémarrage de l'hôte

8

J'exécute Windows 7 dans Virtualbox sur Ubuntu 11.10. Tout fonctionne bien. Je l'exécute au démarrage, mais j'ai un problème avec le redémarrage.

Lorsque je tape, sudo reboot nowl'état du virtuel Windows 7 n'est pas enregistré. Après le redémarrage, la virtualbox démarre, mais au lieu de Windows en cours d'exécution, j'obtiens le menu de démarrage de Windows 7 et les fenêtres redémarrent.

Existe-t-il une option permettant à Ubuntu d'envoyer un signal à la boîte virtuelle pour fermer l'instance en toute sécurité avant le redémarrage de l'hôte?

takhin
la source

Réponses:

6

Dans le cas où vous avez vraiment besoin d'arrêter alors qu'une machine virtuelle dans Virtual Box est en cours d'exécution, vous pouvez définir votre propre script pour un arrêt manuel où vous placez une commande pour enregistrer l'état de la machine avant le début du processus d'arrêt:

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

Alternativement, vous pouvez également générer un script qui s'exécute toujours à l'arrêt .

Takkat
la source
4

Si vous utilisez des sudo rebootprogrammes, le signal de suppression se termine automatiquement sans donner le temps à une application d'agir sur une telle situation. Ce n'est pas un bug, il a toujours fonctionné de la même manière et c'est le comportement attendu.

Il y a une question similaire où vous pouvez voir quelles commandes sont données lorsque vous appuyez sur shutdown, reboot, suspend, bouton etc dans le menu utilisateur, cette solution devrait vous demander ce qu'il faut faire en essayant de fermer une fenêtre avec une application en cours d' exécution et son préférable (en votre cas) à l' sudo shutdownapproche. Regarde

Bruno Pereira
la source
Le redémarrage est-il récemment devenu plus poli? La page de manuel de reboot12.10 indique: "Lorsqu'il est appelé avec --force ou lorsqu'il est au niveau d'exécution 0 ou 6, cet outil appelle lui-même le système de redémarrage (2) et redémarre directement le système. Sinon, cela appelle simplement l'outil d'arrêt (8) avec les arguments appropriés. "; et la page de manuel pour shutdownindique "Une fois TIME écoulé, l'arrêt envoie une demande au démon init (8) pour ramener le système au niveau d'exécution approprié."
echristopherson
4

Je recommanderais une approche plus sophistiquée, y compris un travail parvenu, un script de démarrage et d'arrêt. Par exemple, j'utilise Windows XP, car mon répertoire personnel permet d'utiliser tombert ... que vous devez modifier en conséquence. Il a l'avantage de tout ce que vous faites (redémarrage, arrêt, pression sur le bouton d'alimentation), il gère bien votre machine virtuelle .

Commencez par le travail parvenu, dans /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

Le travail parvenu démarre la machine virtuelle au niveau d'exécution 2 (qui est en mode graphique), et dans mon cas, elle augmente la priorité avec nice. Afin d'arrêter correctement la machine virtuelle, je dois «désactiver» la terminaison parvenu à l'aide de l' kill signal SIGCONTinstruction. Cela laisse la machine virtuelle en cours d'exécution au début (en évitant la valeur par défaut SIGTERM). Après 120 secondes, le SIGKILLest envoyé de toute façon. Au lieu de cela, j'exécute le winxpvm-stop.shscript.

Side-Note 1: Les strophes start on started runlevel [2]et stop on starting runlevel [!2]ne fonctionnent pas. Il faut mentionner spécifiquement le travail rc.

Side-Note 2: Ce qui prête à confusion également dans le manuel du débutant: La kill signalstrophe spécifie le signal envoyé après 5 secondes. Dans cet exemple, je l'ai défini SIGTERM(par défaut) sur SIGCONT - mais le délai d'attente de 5 secondes que je n'ai pas pu modifier. La kill timeoutstrophe spécifie le délai d'attente après lequel le SIGKILLmessage est envoyé - quel signal ne peut pas changer. Une amélioration serait donc de définir de nouvelles strophes term signalet term timeout.

Voici le script de démarrage 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

Étant donné que tous les paramètres, etc. sont effectués en mode utilisateur (car ma connexion est tombert ), même lorsqu'il est exécuté en tant que root, je change le compte en tombert . L'utilisateur pourrait bien sûr être changé dans la configuration upstart mais cette solution me laisse la possibilité de démarrer / arrêter la machine virtuelle "à la main" depuis la console.

Le plus intéressant est le script d'arrêt dans winxpvm-stop.sh:

#! /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

Je fais d'abord la même chose que dans le script de démarrage - je change l'utilisateur de root à mon compte tombert . Voyons maintenant la fonction dostop. Je vérifie d'abord si la machine virtuelle fonctionne même. Ensuite, j'essaie d'arrêter "doucement" en envoyant un arrêt directement à WinXP en utilisant guestcontrol. Ici, vous devez fournir les informations d'identification pour le compte WinXP, qui dans mon cas est tombert et un mot de passe. Windows shutdownfermera normalement toutes les applications et éteindra le système d'exploitation (normalement). Permet ensuite de vérifier en continu l'état de la machine virtuelle showvminfo. Faire cela au moins 60 fois avec un délai d'expiration de 1 seconde (faites ce que vous pensez qu'il est approprié ici) devrait laisser suffisamment de temps à la machine virtuelle pour s'arrêter correctement. Notez que l'appel àshowvminfoprend également un peu moins d'une seconde (au moins sur mon ordinateur), ce qui lui donne ~ 120 secondes dans mon cas. Si tout freine, nous pouvons arrêter de force en utilisant la poweroffdéclaration.

Vous devriez également voir le acpipowerbutton, mais inutilisé. En effet, cela ne fonctionne pas de manière fiable. Si vous êtes connecté à Windows, ou pire encore à plusieurs utilisateurs, Windows affichera une boîte de dialogue d'arrêt de confirmation empêchant le système de s'arrêter. C'est aussi la raison pour laquelle le acpibuttondans le /etc/default/virtualboxne fonctionnera pas à 100% fiable. De plus, la poweroffmachine virtuelle sera arrêtée de force - comme un bouton d'alimentation appuyé longuement. Par conséquent, il est préférable de définir ce paramètre sur vide:

Extrait de / 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=""

Pour le rendre parfait, vous pouvez changer le comportement du bouton d'alimentation:

Extrait de /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
...
...

Il reste un petit inconvénient. Lorsque la machine virtuelle démarre toujours et que le service de contrôle invité n'est pas activé (dans la machine virtuelle), elle ne recevra pas la commande d'arrêt. Un cas rare ... mais pensez-y.

C'est tout, j'espère que ça aide.

tombert
la source
Fonctionne comme un charme (invité Windows XP), sauf qu'il semble jeter un VERR_INVALID_PARAMETERcôté hôte si je suis connecté via RDC en tant qu'utilisateur indiqué dans le script, puis l'invité continue de fonctionner.
echristopherson
J'ai essayé avec les deux, RDC natif et avec RDC sur VirtualBox. Pas une telle erreur. Probablement lié à virtualbox.org/ticket/8197
tombert
2

Suivez cette réponse pour modifier votre stratégie système pour le redémarrage

Vous ne pouvez pas rationaliser cela en reboot. Les init.dscripts AFAIK ne fonctionneront pas car cela prend trop de temps, mais vous pouvez exécuter la commande comme ceci:

VBoxManage controlvm <vm> savestate&&reboot

<vm>est le nom de la machine virtuelle

Amith KK
la source
1

Vous pouvez envoyer une demande d'arrêt à la machine virtuelle avec:

VBoxManage controlvm <vm_name> acpipowerbutton

Mais si vous le faites dans un script d'initialisation, le script ne doit pas se terminer tant que l'arrêt n'est pas terminé. Nous pouvons être en mesure de détecter cela en interrogeant le fichier de lecteur de la machine virtuelle (.vdi) avec lsofou fuseren boucle. Ou comme solution de contournement bon marché, sleep 20peut suffire.

Voici ce que j'utilise actuellement dans le bloc de fermeture de mon script d'initialisation:

# 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

Près du haut du fichier, j'ai défini:

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

Cela ne fermera peut-être pas réellement l'application VirtualBox elle-même, mais cela attend la fin de l'arrêt de la machine virtuelle. De plus, cela ne fonctionne pas si la machine virtuelle est toujours en cours de démarrage (de nombreux systèmes d'exploitation ignorent le bouton de mise hors tension pendant cette phase), ou si vous émulez un ancien système sans prise en charge ACPI.

joeytwiddle
la source