Virtualbox Windows płynne zamykanie gości podczas zamykania hosta

19

Usiłuję znaleźć rozwiązanie, aby z wdziękiem zamknąć wszystkie maszyny wirtualne gościa działające w systemie VirtualBox Windows, gdy komputer hosta zostanie zamknięty lub ponownie uruchomiony.

Wydaje się, że najbezpieczniejszą opcją byłoby uruchomienie polecenia „zapisz stan”, gdy host zaczyna się zamykać, ale nie jest jasne, czy host będzie czekać wystarczająco długo, aż maszyny wirtualne zakończą zapisywanie stanu i wyłączy się.

Czy ktoś ma solidne rozwiązanie tego (pozornie podstawowego) problemu?

Matt Jenkins
źródło
Zainstalować dodatki dla gości? Czy to nie zapewnia wymaganej funkcjonalności?
Kanadyjczyk Luke REINSTATE MONICA,
@CanadianLuke To nie. :)
Matt Jenkins,

Odpowiedzi:

6

Miałem podobny problem i rozwiązałem go, uruchamiając VirtualBox jako usługę:

http://vboxvmservice.sourceforge.net/

Dzięki VBoxVMService możesz wybrać sposób, w jaki urządzenie ma zostać wyłączone (Zapisz stan, wyłącz zasilanie) i uruchomione. Ponieważ działa jako usługa, system Windows będzie automatycznie czekał na zamknięcie podczas procesu zamykania systemu.

Bill Westrup
źródło
Proces konfiguracji nie jest tak automatyczny w systemie Windows 10. Muszę odnieść się do rozwiązywania problemów, aby zobaczyć, co jest nie tak. Jednak po prawidłowym skonfigurowaniu oprogramowanie to robi dokładnie to, czego potrzebuję. Dziękuję za wspaniałą pracę.
iuradz
3

Niestety nie wydaje się to możliwe w przypadku maszyn wirtualnych uruchamianych za pomocą interfejsu GUI VirtualBox. Mimo że GUI może złapać zdarzenie zamknięcia hosta i zareagować, usługa VirtualBox zostaje zakończona: https://forums.virtualbox.org/viewtopic.php?p=278668#p278668

Jeśli nie potrzebujesz konsoli graficznej, możesz wybrać VBoxHeadlessTray lub VBoxVMService. Obie obsługują automatyczne zapisywanie i wznawianie po wyłączeniu i ponownym uruchomieniu hosta Windows.

VirtualBox 5.0 wprowadza tryb startowy „odłączalny interfejs użytkownika” . Ten tryb uruchamia bezgłową maszynę wirtualną z osobnym procesem interfejsu użytkownika. Wydajność graficzna ulega jednak pogorszeniu, a przyspieszenie 3D nie jest jeszcze obsługiwane. Ale może można to w przyszłości połączyć z VBoxHeadlessTray (VBoxHeadlessTray nie obsługuje jeszcze 5.0). Linki do repozytorium GitHub VBoxHeadlessTray i do odpowiedniego żądania ściągnięcia GitHub w celu dodania obsługi VirtualBox 5 .

Edycja: VBoxVmService również nie obsługuje nowego trybu odłączanego od wersji 5.0. Do tej pory tylko bezgłowy . Dodałem do tego prośbę o funkcję .

Lew B.
źródło
Ponieważ nie mogę przenosić więcej niż dwóch linków na post, oto linki do VBoxHeadlessTray i do odpowiedniego żądania ściągnięcia GitHub w celu dodania obsługi VirtualBox 5.
Lew B
Nie występują problemy opisane w wątku. Zobacz moją odpowiedź na ten temat. Mogę zamknąć system hosta Windows i odejść. Zamknij bloki, aż wszystkie moje maszyny wirtualne zostaną zamknięte, a ja zmieniłem domyślną akcję, aby wykonać czyste zamknięcie lub stan zapisu.
Kris Bahnsen
2

Mam 3 skrypty wsadowe, których używam zamiast przycisków zasilania w menu Start.

do_shutdown.bat (zamknij komputer z 10-sekundowym okresem oczekiwania, aby nie dać vm 10 sekund na zapisanie stanu, ale pozwolić mi anulować zamknięcie w ciągu 10 sekund. Odliczanie rozpoczyna się po zamknięciu vm)

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

do_reboot.bat (restartuje się natychmiast po zamknięciu vm)

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

do_cancel.bat (pozwala mi anulować zamknięcie komputera w ciągu 10 sekund. Następnie ponownie uruchamia się vm, ponieważ zostały zamknięte za pomocą do_shutdown.bat)

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

Zamiast savestateciebie możesz również użyć jednego z poniższych

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.
źródło
1
Dzięki, to jest interesujące. Niestety są też inne scenariusze nie-ręcznego zamykania / restartowania. Na przykład ponowne uruchomienie zaplanowane przez usługę Windows Update lub zdarzenia wyłączenia / wyłączenia zasilania z małej baterii.
Matt Jenkins,
1
No dobrze Jest też Edytor zasad grupy z sekcją „Skrypty (uruchamianie / zamykanie)” lifehacker.com/ ... Używam tego do bardzo krótkiego polecenia zamykania (jedno wywołanie curl), więc nie wiem, jak się zachowuje na skryptach, których ukończenie zajmuje trochę czasu.
Daniel F
2

Przepraszam za spóźnienie na imprezę. Jest na to dokładna odpowiedź, choć wymaga ona trochę wiersza polecenia-foo. Zobacz ten wątek, aby uzyskać więcej informacji: https://forums.virtualbox.org/viewtopic.php?f=6&t=53684#p285540

Polecenie, którego szukasz, to:

„C: \ Program Files \ Oracle \ VirtualBox \ VBoxManage.exe” setextradata GUI „VM NAME” / DefaultCloseAction Shutdown

Tego używam na wielu maszynach wirtualnych, zamknij okno i automatycznie rozpocznie się bezpieczne zamknięcie. Zamknij system Windows i podczas próby zamknięcia wszystkiego będzie czekał na zakończenie tych procesów.

Kris Bahnsen
źródło
1

Miałem podobne pytanie i znalazłem tę stronę. Nie chcę uruchamiać VirtualBox jako usługi, ponieważ mam wiele maszyn wirtualnych do testowania i zwykle wybieram różne do uruchomienia w interfejsie VirtualBox. Kiedy zamykam komputer, denerwujące jest ręczne zapisywanie stanu każdej maszyny wirtualnej. Zastosowanie skryptów do zapisania wszystkich działających maszyn wirtualnych wydaje się w tym przypadku praktycznym rozwiązaniem. Aby uogólnić odpowiedź Daniela F., napisałem te skrypty, które automatycznie zapisują stan wszystkich działających maszyn wirtualnych bez wyraźnego nazywania ich.

saveRunningVMs.bat dla 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 dla systemu 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
źródło
0

Utworzyłem skrypt Pythona, który zawiesiłby wszystkie działające maszyny wirtualne VirtualBox, a następnie skonfigurowałem system do uruchamiania skryptu podczas wylogowywania jako zaplanowane zadanie.

Nie wiem, jak niezawodna jest ta metoda. Jak zauważyli inni, istnieją ograniczenia dotyczące czasu oczekiwania systemu na zakończenie zadania Winlogon 7002. Ale ja osobiście nie miałem z tym problemu, dając użyteczne stany zapisu, nawet przy wielu działających maszynach wirtualnych na ponad 4 GB ogólnej pamięci RAM maszyny wirtualnej.

Oto kroki, aby to skonfigurować:

  1. Pobierz i zainstaluj Python 2.7.x ze strony python.org
  2. Utwórz plik skryptu python gdzieś w systemie za pomocą Notatnika lub innego edytora zwykłego tekstu (patrz poniżej)
  3. Otwórz Harmonogram zadań
  4. Wybierz polecenie Działanie -> Utwórz zadanie podstawowe ... i użyj kreatora, aby utworzyć zadanie z następującymi ustawieniami
    • Imię twojego wyboru
    • Uruchom zadanie po zarejestrowaniu określonego zdarzenia
    • Log: System
    • Źródło: Winlogon
    • Identyfikator zdarzenia: 7002
    • Uruchom program
    • Obok programu / skryptu , wprowadź pełną ścieżkę dostępu do python.exe, na przykładc:\Python27\python.exe
    • Obok opcji Dodaj argumenty podaj pełną ścieżkę do pliku skryptu Pythona, na przykład umieściłem mój w podfolderze folderu moich dokumentów, więc jest toC:\Users\rakslice\Documents\vboxsuspend\vboxsuspend.py
    • Wybierz Zakończ.

Teraz maszyny wirtualne VirtualBox powinny zostać zawieszone przy wylogowaniu / ponownym uruchomieniu / zamknięciu.

Skrypt Pythona do zamykania systemu znajduje się poniżej:

# 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
źródło
1
Sugestia innych osób dotycząca użycia skryptu wsadowego, który można uruchomić ręcznie, który wykonuje zapisywanie stanów, a następnie wyłączanie, jest świetna, jeśli pasuje do twojego przypadku użycia. Ale to, co naprawdę chcę to do Windows Update jest automatyczne ponowne uruchamianie po VM pracuję z twardego został wyłączony przez noc uruchomieniu Windows Update przez ostatnie dwa dni z rzędu ...
rakslice