Cierre de forma segura la máquina virtualbox al reiniciar el host

8

Estoy ejecutando Windows 7 dentro de Virtualbox en Ubuntu 11.10. Todo funciona bien Lo estoy ejecutando al inicio, pero tengo un problema con el reinicio.

Cuando escribo, sudo reboot nowel estado de Windows 7 virtual no se guarda. Después del reinicio, se inicia virtualbox, pero en lugar de ejecutar Windows, obtengo el menú de inicio de bloqueo de Windows 7 y Windows se inicia nuevamente.

¿Existe alguna opción de que Ubuntu pueda enviar alguna señal a la caja virtual para cerrar de forma segura la instancia antes de reiniciar el host?

tomashin
fuente

Respuestas:

6

En caso de que realmente necesite apagarse mientras se está ejecutando una máquina virtual en Virtual Box, puede definir su propio script para un apagado manual donde coloque un comando para guardar el estado de la máquina antes de que comience el proceso de apagado:

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

Alternativamente, también podría generar un script que siempre se ejecute al apagar .

Takkat
fuente
4

Si usa sudo rebootprogramas, se le dará la señal de finalización automáticamente sin dar tiempo a la aplicación para actuar en tal situación. Esto no es un error, siempre ha funcionado de la misma manera y ese es el comportamiento esperado.

Hay una pregunta similar donde se puede ver qué órdenes se dan cuando se pulsa el shutdown, reboot, suspend, botón, etc. en el menú de usuario, tal solución debe preguntar qué hacer cuando se trata de cerrar una ventana con una aplicación que se ejecuta y su preferible (en su caso) al sudo shutdownenfoque. Echar un vistazo

Bruno Pereira
fuente
¿El reinicio se ha vuelto más cortés recientemente? La página del manual de reboot12.10 dice "Cuando se llama con --force o cuando está en el nivel de ejecución 0 o 6, esta herramienta invoca el sistema reiniciar (2), se llama a sí mismo y reinicia directamente el sistema. De lo contrario, esto simplemente invoca la herramienta de apagado (8) con los argumentos apropiados "; y la página del manual shutdowndice "Una vez que ha transcurrido el TIEMPO, el apagado envía una solicitud al demonio init (8) para que el sistema baje al nivel de ejecución apropiado".
echristopherson el
4

Recomendaría un enfoque más sofisticado que incluye un trabajo inicial, un script de inicio y detención. Como ejemplo, estoy usando Windows XP, ya que mi directorio de inicio permite usar tombert ... que debes cambiar en consecuencia. Tiene la ventaja de lo que sea que haga (reiniciar, apagar, presionar el botón de encendido), maneja su máquina virtual muy bien .

Primero el trabajo inicial, poner en /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

El trabajo inicial inicia la máquina virtual en el nivel de ejecución 2 (que está en modo gráfico), y en mi caso aumenta la prioridad con nice. Para poder apagar la máquina virtual, necesito "deshabilitar" la terminación de inicio utilizando la kill signal SIGCONTinstrucción. Esto deja la máquina virtual ejecutándose al principio (evitando el valor predeterminado SIGTERM). Después de 120 segundos, SIGKILLse envía de todos modos. En cambio, estoy ejecutando el winxpvm-stop.shscript.

Nota al margen 1: Las estrofas start on started runlevel [2]y stop on starting runlevel [!2]no funcionan. Hay que mencionar específicamente el trabajo rc.

Nota al margen 2: Lo que es confuso también en el manual inicial: la kill signalestrofa especifica la señal enviada después de 5 segundos. En este ejemplo, lo configuré de SIGTERM(predeterminado) a SIGCONT, pero no pude cambiar el tiempo de espera de 5 segundos. La kill timeoutestrofa especifica el tiempo de espera después del cual SIGKILLse envía, qué señal no se puede cambiar. Por lo tanto, una mejora sería definir nuevas estrofas term signaly term timeout.

Aquí el script de inicio 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

Dado que todas las configuraciones, etc., se realizan en modo de usuario (ya que mi inicio de sesión es tombert ), incluso cuando se ejecuta como root, cambio la cuenta a tombert . El usuario, por supuesto, podría cambiar en la configuración inicial, pero esta solución me deja la opción de iniciar / detener la máquina virtual "a mano" desde la consola.

Lo más interesante es el script de apagado en 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

Primero hago lo mismo que en el script de inicio: estoy cambiando el usuario de root a mi cuenta tombert . Ahora veamos la función dostop. Primero estoy verificando si la máquina virtual está funcionando. Entonces estoy tratando de apagar "suavemente" enviando un apagado directamente a WinXP usando guestcontrol. Aquí debe proporcionar las credenciales para la cuenta WinXP, que en mi caso es tombert y una contraseña. Windows shutdowncerrará con gracia todas las aplicaciones y apagará el sistema operativo (normalmente). Luego, verifiquemos el estado de la máquina virtual continuamente usando showvminfo. Hacer esto al menos 60 veces con 1 segundo de tiempo de espera (haga lo que considere apropiado aquí) debería dejar a la máquina virtual el tiempo suficiente para apagarse correctamente. Tenga en cuenta que la llamada ashowvminfoTambién toma un poco menos de un segundo (al menos en mi computadora), por lo que esto me da ~ 120 segundos en mi caso. Si todo se frena, podemos apagarlo forzosamente usando la poweroffdeclaración.

También debería ver el acpipowerbutton, pero sin usar. Esto se debe a que no funciona de manera confiable. Si ha iniciado sesión en Windows o, lo que es peor, en varios usuarios, Windows mostrará un diálogo de confirmación de apagado que evitará que el sistema se apague. Esta es también la razón por acpibuttonla /etc/default/virtualboxcual no funcionará 100% confiable. Además poweroff, la máquina virtual se apagará por la fuerza, igual que un botón de encendido de larga duración. Por lo tanto, es mejor configurar esto para vaciar:

Extracto 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=""

Para que sea perfecto, es posible que desee cambiar el comportamiento del botón de encendido:

Extracto 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
...
...

Queda un pequeño inconveniente. Cuando la máquina virtual todavía se está iniciando y el servicio de control de invitados no está activo (en la máquina virtual), no recibirá el comando de apagado. Un caso raro ... pero piénsalo.

Eso es, espero que ayude.

tombert
fuente
Funciona de maravilla (invitado de Windows XP), excepto que parece arrojar un VERR_INVALID_PARAMETERen el lado del host si estoy conectado a través de RDC como el usuario dado en el script, y posteriormente el invitado sigue ejecutándose.
echristopherson el
Intenté con ambos, RDC nativo y con RDC encima de VirtualBox. No hay tal error. Probablemente relacionado con virtualbox.org/ticket/8197
tombert
2

Siga esta respuesta para cambiar la política de su sistema para reiniciar

No puedes simplificar esto reboot. Los init.dscripts AFAIK no funcionarán porque lleva demasiado tiempo, pero puede ejecutar el comando de esta manera:

VBoxManage controlvm <vm> savestate&&reboot

donde <vm>está el nombre de la máquina virtual

Amith KK
fuente
1

Puede enviar una solicitud de apagado a la máquina virtual con:

VBoxManage controlvm <vm_name> acpipowerbutton

Pero si hace esto en un guión de inicio, el guión no debería salir hasta que se haya completado el apagado. Es posible que podamos detectar eso al sondear el archivo de unidad de VM (.vdi) con lsofo fuseren un bucle. O como una solución económica, sleep 20puede ser suficiente.

Esto es lo que estoy usando actualmente en el bloque cerrado de mi script de inicio:

# 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

Cerca de la parte superior del archivo que definí:

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

Es posible que esto no cierre la aplicación VirtualBox en sí, pero sí espera a que la máquina virtual se cierre por completo. Además, no funciona si la máquina virtual todavía está en proceso de arranque (muchos sistemas operativos ignoran el botón de apagado durante esta fase), o si está emulando un sistema antiguo sin soporte ACPI.

joeytwiddle
fuente