Windows Virtualbox desligamento normal de convidados no desligamento do host

19

Estou tentando encontrar uma solução para encerrar normalmente todas as VMs convidadas em execução no VirtualBox Windows quando o computador host for desligado ou reiniciado.

Parece que a opção mais segura seria acionar o comando "salvar estado" quando o host começar a desligar, mas não está claro se o host aguardará tempo suficiente para que as VMs terminem de salvar o estado e desliguem.

Alguém tem uma solução robusta para esse problema (aparentemente básico)?

Matt Jenkins
fonte
Instalar as adições de convidados? Isso não fornece a funcionalidade necessária?
Canadian Luke REINSTATE MONICA
@CanadianLuke Isso não acontece. :)
Matt Jenkins

Respostas:

6

Eu tive um problema semelhante e o resolvi executando o VirtualBox como um serviço:

http://vboxvmservice.sourceforge.net/

Com o VBoxVMService, você pode escolher como deseja que a máquina seja desligada (Salvar estado, desligado) e iniciada. Como está sendo executado como um serviço, o Windows espera automaticamente o desligamento durante o processo de desligamento do sistema.

Bill Westrup
fonte
O processo de configuração não é tão automático no Windows 10. Tenho que me referir à solução de problemas para ver o que há de errado. No entanto, depois de configurado corretamente, este software faz exatamente o que eu preciso. Obrigado por seu ótimo trabalho.
Iuradz
3

Infelizmente, isso não parece possível para VMs iniciadas via GUI do VirtualBox. Embora a GUI possa pegar o evento de desligamento do host e reagir, o serviço VirtualBox é encerrado: https://forums.virtualbox.org/viewtopic.php?p=278668#p278668

Se você não precisar de um console gráfico, o VBoxHeadlessTray ou o VBoxVMService pode ser o caminho a seguir. Ambos suportam salvamento e retomada automáticos no desligamento e reinicialização do host do Windows.

O VirtualBox 5.0 apresenta um modo de inicialização "interface do usuário destacável" . Esse modo inicia uma VM sem cabeçalho com um processo de interface do usuário separado. Porém, o desempenho gráfico sofre e a aceleração 3D ainda não é suportada. Mas talvez isso possa ser combinado com o VBoxHeadlessTray no futuro (o VBoxHeadlessTray ainda não suporta 5.0). Links para o repositório do GitHub do VBoxHeadlessTray e para a solicitação de recebimento do GitHub correspondente para adicionar suporte ao VirtualBox 5 .

Edit: VBoxVmService também não suporta o novo modo destacável a partir da versão 5.0. Apenas sem cabeça até agora. Eu adicionei uma solicitação de recurso para isso.

Leo B
fonte
Como não tenho permissão para portar mais de dois links por postagem, aqui estão os links para VBoxHeadlessTray e a solicitação pull correspondente do GitHub para adicionar suporte ao VirtualBox 5.
Leo B
Não encontro os problemas descritos no tópico. Veja minha resposta sobre este tópico. Eu posso executar o desligamento do host do Windows e ir embora. O desligamento é bloqueado até que todas as minhas VMs sejam fechadas e eu mudei a ação padrão para fazer um desligamento limpo ou salvar um estado.
Kris Bahnsen
2

Eu tenho 3 scripts em lote que eu uso em vez dos botões de energia do menu Iniciar.

do_shutdown.bat (desligar o pc com um período de espera de 10 segundos, não para dar tempo de economia de 10 segundos para a VM, mas para permitir que eu cancele o desligamento em 10 segundos. A contagem regressiva começa depois que a VM foi desligada)

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

do_reboot.bat (reinicia imediatamente após o encerramento da VM)

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

do_cancel.bat (permite cancelar o desligamento do PC dentro do período de espera de 10 segundos. Em seguida, reinicia os vm novamente, pois eles foram desligados com o do_shutdown.bat)

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

Em vez de savestatevocê também pode usar um dos seguintes

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
fonte
1
Obrigado, isso é interessante. Infelizmente, existem outros cenários não manuais de desligamento / reinicialização que também precisam ser resolvidos. Por exemplo, reinicializações agendadas pelo Windows Update ou eventos de desligamento / desligamento da bateria fraca.
Matt Jenkins
1
Ah ok. Há também o Group Policy Editor com as "Scripts (inicialização / desligamento)" seção lifehacker.com/... eu estou usando esse para um período muito curto de comando no desligamento (uma chamada curl), então eu não sei como ele se comporta em scripts que demoram um pouco para serem concluídos.
Daniel F
2

Desculpe o atraso na festa. Existe uma resposta exata para isso, embora exija algum comando-foo. Consulte esta publicação no tópico para obter mais informações: https://forums.virtualbox.org/viewtopic.php?f=6&t=53684#p285540

O comando que você está procurando é:

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

É isso que eu uso em várias VMs, fecho a janela e ele inicia um desligamento seguro automaticamente. Desligue o Windows e, na tentativa de fechar tudo, aguardará a conclusão desses processos.

Kris Bahnsen
fonte
1

Eu tive uma pergunta semelhante e encontrei esta página. Não quero executar o VirtualBox como um serviço, porque tenho muitas VMs para teste e geralmente escolho diferentes para executar na interface do usuário do VirtualBox. Quando eu desligo o computador, é chato salvar manualmente o estado de cada VM. Usar scripts para salvar todas as VMs em execução parece ser uma solução prática nesse caso. Para tornar a resposta de Daniel F mais geral, escrevi esses scripts que salvam automaticamente o estado de todas as VMs em execução sem nomeá-las explicitamente.

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
fonte
0

Criei um script python que suspenderia todas as VMs do VirtualBox em execução e configurei o sistema para executar o script no logout como uma tarefa agendada.

Não sei exatamente como esse método é confiável. Como outros observaram, há limites para quanto tempo o sistema aguardará a conclusão de uma tarefa do Winlogon 7002. Mas, pessoalmente, não tive nenhum problema em fornecer estados de salvamento utilizáveis, mesmo com várias VMs em execução em mais de 4 GB de RAM geral da VM.

Aqui estão as etapas para configurá-lo:

  1. Baixe e instale o Python 2.7.x em python.org
  2. Crie o arquivo de script python em algum lugar do seu sistema usando o Bloco de notas ou qualquer outro editor de texto sem formatação (veja abaixo)
  3. Agendador de tarefas aberto
  4. Escolha Ação -> Criar uma tarefa básica ... e use o assistente para criar uma tarefa com as seguintes configurações
    • Um nome de sua escolha
    • Inicie a tarefa quando um evento específico for registrado
    • Log: Sistema
    • Fonte: Winlogon
    • ID do Evento: 7002
    • Iniciar um programa
    • Ao lado de Programa / Script , digite o caminho completo para o seu python.exe, por exemploc:\Python27\python.exe
    • Ao lado de Adicionar argumentos , digite o caminho completo em que você coloca o arquivo de script python, por exemplo, eu coloquei o meu em uma subpasta da minha pasta de documentos.C:\Users\rakslice\Documents\vboxsuspend\vboxsuspend.py
    • Escolha Concluir.

Agora as VMs do VirtualBox devem ser suspensas no logout / reinício / desligamento.

O script python para fazer o desligamento está abaixo:

# 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
fonte
1
A sugestão de outras pessoas de usar um script em lote que você pode executar manualmente que faz savestates e, em seguida, encerra é ótimo se isso se adequar ao seu caso de uso. Mas o que eu realmente quero isso para é Windows Update reinicializações automáticas, depois de uma VM eu tenho trabalhado com foi difícil desligado durante a noite pelo Windows Update é reiniciado durante os últimos dois dias em uma fila ...
rakslice