Virtualbox Windows apagado elegante de invitados en el apagado del host

19

Estoy tratando de encontrar una solución para apagar con gracia cualquier máquina virtual invitada que se ejecute en VirtualBox Windows cuando la computadora host se apaga o reinicia.

Parece que la opción más segura sería activar el comando "guardar estado" cuando el host comienza a apagarse, pero no está claro si el host esperará lo suficiente para que las máquinas virtuales terminen de guardar el estado y se apaguen.

¿Alguien tiene una solución sólida para este problema (aparentemente básico)?

Matt Jenkins
fuente
Instalar las adiciones de invitados? ¿Eso no proporciona la funcionalidad requerida?
Canadian Luke REINSTATE MONICA
@CanadianLuke No lo hace. :)
Matt Jenkins el

Respuestas:

6

Tuve un problema similar y lo resolví ejecutando VirtualBox como servicio:

http://vboxvmservice.sourceforge.net/

Con VBoxVMService puede elegir cómo quiere que la máquina se apague (Guardar estado, apagado) y arranque. Como se está ejecutando como un servicio, Windows esperará automáticamente a que se apague durante el proceso de apagado del sistema.

Bill Westrup
fuente
El proceso de configuración no es tan automático en Windows 10. Tengo que referirme a la solución de problemas para ver qué pasa. Sin embargo, después de configurarlo correctamente, este software hace exactamente lo que necesito. Gracias por tu gran trabajo.
iuradz
3

Desafortunadamente, eso no parece ser posible para las máquinas virtuales iniciadas a través de VirtualBox GUI. Aunque la GUI puede detectar el evento de apagado del host y reaccionar, el servicio VirtualBox se termina: https://forums.virtualbox.org/viewtopic.php?p=278668#p278668

Si no necesita una consola gráfica, VBoxHeadlessTray o VBoxVMService pueden ser el camino a seguir. Ambos admiten guardar y reanudar automáticamente en el apagado y reinicio del host de Windows.

VirtualBox 5.0 presenta un modo de inicio "UI desmontable" . Este modo inicia una VM sin cabeza con un proceso de IU separado. Sin embargo, el rendimiento gráfico sufre y la aceleración 3D aún no es compatible. Pero tal vez esto se pueda combinar con VBoxHeadlessTray en el futuro (VBoxHeadlessTray aún no es compatible con 5.0). Enlaces al repositorio de VBoxHeadlessTray GitHub y a la solicitud de extracción de GitHub correspondiente para agregar soporte para VirtualBox 5 .

Editar: VBoxVmService tampoco es compatible con el nuevo modo desmontable a partir de la versión 5.0. Solo sin cabeza hasta ahora. Agregué una solicitud de función para eso.

Leo B
fuente
Como no se me permite portar más de dos enlaces por publicación, aquí están los enlaces a VBoxHeadlessTray y a la solicitud de extracción de GitHub correspondiente para agregar compatibilidad con VirtualBox 5.
Leo B
No experimento los problemas descritos en el hilo. Vea mi respuesta sobre este tema. Puedo ejecutar el apagado del host de Windows y alejarme. Apague los bloques hasta que todas mis máquinas virtuales estén cerradas, y he cambiado la acción predeterminada para hacer un apagado limpio o un estado de guardar.
Kris Bahnsen
2

Tengo 3 scripts por lotes que utilizo en lugar de los botones de encendido del menú de inicio.

do_shutdown.bat (apagado de la PC con un período de espera de 10 segundos, no para dar tiempo de 10 segundos a la vm para guardar el estado, sino para permitirme cancelar el apagado en 10 segundos. La cuenta regresiva comienza después de que las vm se hayan apagado)

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

do_reboot.bat (se reinicia inmediatamente después de que se cierre el vm)

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

do_cancel.bat (me permite cancelar el apagado de la PC dentro del período de espera de 10 segundos. Luego reinicia los vm nuevamente, ya que se cerraron con el do_shutdown.bat)

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

En lugar de savestateusted también puede usar uno de los siguientes

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
fuente
1
Gracias, esto es interesante. Desafortunadamente, hay otros escenarios de apagado / reinicio no manuales que también debo manejar. Por ejemplo, reinicios programados por Windows Update o eventos de apagado / apagado de batería baja.
Matt Jenkins el
1
Oh ok También está el Editor de directivas de grupo con la sección "Scripts (inicio / apagado)" lifehacker.com/… Estoy usando ese para un comando muy corto en el apagado (una llamada curl), así que no sé cómo se comporta en guiones que tardan un tiempo en completarse.
Daniel F
2

Lo siento, llego tarde a la fiesta. Hay una respuesta exacta a esto, aunque requiere algo de línea de comandos-foo. Consulte esta publicación de hilo para obtener más información: https://forums.virtualbox.org/viewtopic.php?f=6&t=53684#p285540

El comando que estás buscando es:

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

Esto es lo que uso en varias máquinas virtuales, cierro la ventana y se inicia automáticamente un apagado seguro. Apague Windows y, en su intento de cerrar todo, esperará a que se completen estos procesos.

Kris Bahnsen
fuente
1

Tuve una pregunta similar y encontré esta página. No quiero ejecutar VirtualBox como un servicio, porque tengo muchas máquinas virtuales para probar, y generalmente elijo diferentes para ejecutar en la interfaz de usuario de VirtualBox. Cuando apago mi computadora, es molesto guardar manualmente el estado de cada VM. El uso de scripts para guardar todas las máquinas virtuales en ejecución parece ser una solución práctica en este caso. Para hacer la respuesta de Daniel F más general, escribí estos scripts que guardan automáticamente el estado de todas las máquinas virtuales en ejecución sin nombrarlas explícitamente.

saveRunningVMs.bat para 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 para 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
fuente
0

Creé un script de Python que suspendería todas las máquinas virtuales de VirtualBox en ejecución y luego configuré el sistema para ejecutar el script al cerrar sesión como una tarea programada.

No sé qué tan confiable es este método exactamente. Como otros han señalado, hay límites en cuanto al tiempo que el sistema esperará a que se complete una tarea de Winlogon 7002. Pero, personalmente, no he tenido ningún problema al proporcionar estados de guardado utilizables incluso con múltiples máquinas virtuales en ejecución en más de 4 GB de RAM de VM en general.

Estos son los pasos para configurarlo:

  1. Descargue e instale Python 2.7.x desde python.org
  2. Cree el archivo de secuencia de comandos de Python en algún lugar de su sistema con el Bloc de notas o cualquier otro editor de texto sin formato (consulte a continuación)
  3. Abrir programador de tareas
  4. Elija Acción -> Crear una tarea básica ... y use el asistente para crear una tarea con la siguiente configuración
    • Un nombre de tu elección
    • Inicie la tarea cuando se registra un evento específico
    • Registro: sistema
    • Fuente: Winlogon
    • Id. De evento: 7002
    • Comience un programa
    • Junto a Programa / Script , ingrese la ruta completa a su python.exe, por ejemploc:\Python27\python.exe
    • Junto a Agregar argumentos , ingrese la ruta completa donde coloca el archivo de secuencia de comandos de Python, por ejemplo, coloco el mío en una subcarpeta de mi carpeta de documentos, así que esto esC:\Users\rakslice\Documents\vboxsuspend\vboxsuspend.py
    • Elige Finalizar.

Ahora las máquinas virtuales de VirtualBox deberían suspenderse al cerrar sesión / reiniciar / apagar.

La secuencia de comandos de Python para hacer el apagado está a continuación:

# 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
fuente
1
La sugerencia de otros de usar un script por lotes que puede ejecutar manualmente que realiza los estados guardados y luego el apagado es excelente si se ajusta a su caso de uso. Pero para lo que realmente quiero esto es para los reinicios automáticos de Windows Update, después de que una VM con la que he estado trabajando haya sido apagada durante la noche por Windows Update reinicia durante los últimos dos días seguidos ...
rakslice