17

Я пытаюсь найти решение для корректного завершения работы любых гостевых виртуальных машин, работающих под Windows VirtualBox, когда главный компьютер выключен или перезапущен.

Кажется, что наиболее безопасным вариантом будет запуск команды "сохранить состояние", когда хост начинает отключаться, но неясно, будет ли хост ждать достаточно долго, чтобы виртуальные машины завершили сохранение состояния и отключили питание.

У кого-нибудь есть надежное решение этой (на первый взгляд основной) проблемы?

6 ответов6

6

У меня была похожая проблема, и я решил ее, запустив VirtualBox как сервис:

http://vboxvmservice.sourceforge.net/

С VBoxVMService вы можете выбрать, как вы хотите выключить машину (сохранить состояние, отключить питание) и запустить. Поскольку он работает как служба, Windows автоматически будет ждать его завершения во время процесса выключения системы.

3

К сожалению, это не представляется возможным для виртуальных машин, запущенных через VirtualBox GUI. Даже если графический интерфейс может перехватить событие отключения хоста и отреагировать, служба VirtualBox прекратит работу: https://forums.virtualbox.org/viewtopic.php?p=278668#p278668

Если вам не нужна графическая консоль, VBoxHeadlessTray или VBoxVMService могут помочь. Оба поддерживают автоматическое сохранение и возобновление работы при выключении и перезагрузке хоста Windows.

VirtualBox 5.0 вводит режим запуска "отсоединяемый пользовательский интерфейс". Этот режим запускает безголовую виртуальную машину с отдельным процессом пользовательского интерфейса. Графическая производительность страдает, а 3D-ускорение пока не поддерживается. Но, возможно, это может быть объединено с VBoxHeadlessTray в будущем (VBoxHeadlessTray пока не поддерживает 5.0). Ссылки на репозиторий VBoxHeadlessTray GitHub и соответствующий запрос GitHub для добавления поддержки VirtualBox 5.

Изменить: VBoxVmService также не поддерживает новый режим отсоединения начиная с версии 5.0. Пока только без головы . Я добавил запрос функции для этого.

2

Извините, я опоздал на вечеринку. Существует точный ответ на это, хотя для этого требуется некоторая командная строка-foo Посмотрите эту тему для получения дополнительной информации: https://forums.virtualbox.org/viewtopic.php?f=6&t=53684#p285540

Команда, которую вы ищете:

"C:\Program Files\Oracle\VirtualBox\VBoxManage.exe" setextradata "ИМЯ Виртуальной машины" GUI/DefaultCloseAction Завершение работы

Это то, что я использую на нескольких виртуальных машинах, закройте окно, и оно автоматически начнет безопасное отключение. Завершите работу Windows и при попытке закрыть все будет ждать завершения этих процессов.

1

У меня был похожий вопрос и я нашел эту страницу. Я не хочу запускать VirtualBox как сервис, потому что у меня много виртуальных машин для тестирования, и я обычно выбираю разные для запуска в пользовательском интерфейсе VirtualBox. Когда я выключаю свой компьютер, раздражает ручное сохранение состояния каждой виртуальной машины. Использование сценариев для сохранения всех работающих виртуальных машин представляется в этом случае практическим решением. Чтобы сделать ответ Даниэля Ф. более общим, я написал эти сценарии, которые автоматически сохраняют состояние всех работающих виртуальных машин, не называя их явно.

saveRunningVMs.bat для 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 для 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
1

У меня есть 3 пакетных сценария, которые я использую вместо кнопок питания в стартовом меню.

do_shutdown.bat (завершение работы компьютера с 10- секундным периодом ожидания, чтобы не дать виртуальному виртуальному компьютеру 10-секундное время для сохранения, но чтобы я мог отменить выключение в течение 10 секунд. Обратный отсчет начинается после закрытия виртуальной машины)

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

do_reboot.bat (перезагружается сразу после закрытия виртуальной машины )

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

do_cancel.bat (позволяет мне отменить выключение компьютера в течение 10 секунд ожидания. Затем он снова перезапускает виртуальные машины, так как они закрываются с помощью do_shutdown.bat)

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

Вместо savestate вы также можете использовать один из следующих

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

Я создал скрипт Python, который приостановил бы все работающие виртуальные машины VirtualBox, а затем настроил систему для запуска сценария при выходе из системы в качестве запланированной задачи.

Я не знаю, насколько надежен этот метод. Как уже отмечали другие, существуют ограничения на то, как долго система будет ждать завершения задачи Winlogon 7002. Но лично у меня не было никаких проблем с предоставлением полезных состояний сохранения даже с несколькими запущенными виртуальными машинами на 4+ ГБ общей виртуальной памяти.

Вот шаги, чтобы настроить это:

  1. Загрузите и установите Python 2.7.x с python.org
  2. Создайте файл скрипта Python где-нибудь в вашей системе, используя Блокнот или любой другой текстовый редактор (см. Ниже).
  3. Открыть планировщик заданий
  4. Выберите «Действие» -> «Создать базовую задачу» и с помощью мастера создайте задачу со следующими настройками.
    • Имя по вашему выбору
    • Запустите задачу, когда определенное событие зарегистрировано
    • Журнал: Система
    • Источник: Winlogon
    • Код события: 7002
    • Начать программу
    • Рядом с программой / скриптом введите полный путь к вашему python.exe , например c:\Python27\python.exe
    • Рядом с полем Добавить аргументы введите полный путь, куда вы помещаете файл скрипта Python, например, я помещаю свой в подпапку папки с документами, так что это C:\Users\rakslice\Documents\vboxsuspend\vboxsuspend.py
    • Выберите Готово.

Теперь виртуальные машины VirtualBox должны быть приостановлены при выходе из системы / перезагрузке / завершении работы.

Скрипт python для выключения находится ниже:

# 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()

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .