호스트 종료시 Virtualbox Windows가 정상적으로 게스트 종료 가장 안전한 옵션이지만 VM이 상태 저장을 마치고

호스트 컴퓨터가 종료되거나 다시 시작될 때 VirtualBox Windows에서 실행되는 게스트 VM을 정상적으로 종료하는 솔루션을 찾으려고합니다.

호스트가 종료되기 시작할 때 “save state”명령을 트리거하는 것이 가장 안전한 옵션이지만 VM이 상태 저장을 마치고 전원이 꺼질 때까지 호스트가 오래 기다릴 지 여부는 확실하지 않습니다.

누구나이 문제에 대한 강력한 해결책이 있습니까?



답변

비슷한 문제가 있었고 VirtualBox를 서비스로 실행하여 해결했습니다.

http://vboxvmservice.sourceforge.net/

VBoxVMService를 사용하면 시스템 종료 (저장 상태, 전원 끄기) 및 시작 방법을 선택할 수 있습니다. 서비스로 실행 중이므로 Windows는 시스템 종료 프로세스 중에 자동으로 종료 될 때까지 기다립니다.


답변

불행히도 VirtualBox GUI를 통해 VM을 시작한 경우에는 불가능한 것 같습니다. GUI가 호스트 종료 이벤트를 포착하여 반응하더라도 VirtualBox 서비스가 종료됩니다. https://forums.virtualbox.org/viewtopic.php?p=278668#p278668

그래픽 콘솔이 필요하지 않은 경우 VBoxHeadlessTray 또는 VBoxVMService를 사용하는 것이 좋습니다. 둘 다 Windows 호스트 종료 및 재시작시 자동 저장 및 재개를 지원합니다.

VirtualBox 5.0에는 “분리 가능한 UI” 시작 모드가 도입되었습니다 . 이 모드는 별도의 UI 프로세스로 헤드리스 VM을 시작합니다. 그래도 그래픽 성능이 저하되고 3D 가속은 아직 지원되지 않습니다. 그러나 이것은 나중에 VBoxHeadlessTray와 결합 될 수 있습니다 (VBoxHeadlessTray는 아직 5.0을 지원하지 않습니다.) VBoxHeadlessTray GitHub 리포지토리VirtualBox 5 지원 추가를위한 해당 GitHub 풀 요청에 대한 링크 .

편집 : VBoxVmService는 버전 5.0부터 새로운 분리 가능 모드를 지원하지 않습니다 . 만 헤드리스 지금까지. 이에 대한 기능 요청 을 추가했습니다 .


답변

시작 메뉴 전원 버튼 대신 3 개의 배치 스크립트가 있습니다.

do_shutdown.bat (10 초 대기 시간이있는 종료 PC, vm의 10 초 시간을 savestate에 제공하지 않고 10 초 내에 종료를 취소 할 수 있도록합니다. vm이 종료 된 후 카운트 다운이 시작됨)

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

do_reboot.bat (vm이 종료 된 직후 재부팅)

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

do_cancel.bat (10 초 대기 기간 내에 pc-shutdown을 취소 할 수 있습니다. 그런 다음 do_shutdown.bat로 종료되었으므로 vm을 다시 시작합니다)

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)

답변

파티에 늦어서 미안해 약간의 commandline-foo가 필요하지만 이것에 대한 정확한 대답이 있습니다. 자세한 내용은이 게시물을 참조하십시오 : https://forums.virtualbox.org/viewtopic.php?f=6&t=53684#p285540

찾고있는 명령은 다음과 같습니다.

“C : \ Program Files \ Oracle \ VirtualBox \ VBoxManage.exe”setextradata “VM NAME”GUI / DefaultCloseAction 종료

이것은 여러 VM에서 사용하는 창이며 창을 닫고 안전한 종료를 자동으로 시작합니다. Windows를 종료하고 모든 것을 닫으려고 시도하면 이러한 프로세스가 완료 될 때까지 기다립니다.


답변

비슷한 질문이 있었고이 페이지를 찾았습니다. 테스트를 위해 많은 VM이 있고 일반적으로 VirtualBox UI에서 실행할 다른 VM을 선택하기 때문에 VirtualBox를 서비스로 실행하고 싶지 않습니다. 컴퓨터를 종료하면 각 VM의 상태를 수동으로 저장하는 것이 번거 롭습니다. 이 경우 스크립트를 사용하여 실행중인 모든 VM을 저장하는 것이 실용적인 솔루션 인 것 같습니다. Daniel F의 답변을보다 일반적으로 만들기 위해, 실행중인 모든 VM의 상태를 명시 적으로 명명하지 않고 자동으로 저장하는이 스크립트를 작성했습니다.

Windows 용 saveRunningVMs.bat :

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

Linux의 경우 saveRunningVMs.sh :

#!/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

답변

실행중인 모든 VirtualBox VM을 일시 중단하는 Python 스크립트를 만든 다음 로그 아웃시 스크립트를 예약 된 작업으로 실행하도록 시스템을 설정했습니다.

이 방법이 얼마나 안정적인지 잘 모르겠습니다. 다른 사람들이 언급했듯이 시스템이 Winlogon 7002 작업이 완료되기를 기다리는 시간에는 제한이 있습니다. 그러나 개인적으로 4GB 이상의 전체 VM RAM에서 여러 개의 실행중인 VM에서도 사용 가능한 저장 상태를 제공하는 데 아무런 문제가 없었습니다.

설정 단계는 다음과 같습니다.

  1. python.org에서 Python 2.7.x 다운로드 및 설치
  2. 메모장이나 다른 일반 텍스트 편집기를 사용하여 시스템 어딘가에 파이썬 스크립트 파일을 만듭니다 (아래 참조).
  3. 작업 스케줄러 열기
  4. 조치-> 기본 태스크 작성 …을 선택하고 마법사를 사용하여 다음 설정으로 태스크를 작성하십시오.
    • 선택한 이름
    • 특정 이벤트가 기록되면 작업을 시작합니다
    • 로그 : 시스템
    • 출처 : Winlogon
    • 이벤트 ID : 7002
    • 프로그램 시작
    • 옆에 프로그램 / 스크립트 , 당신의 전체 경로를 입력 python.exe예를 들어,c:\Python27\python.exe
    • 인수 추가 옆에 파이썬 스크립트 파일을 넣는 전체 경로를 입력하십시오. 예를 들어 문서 폴더의 하위 폴더에 광산을 넣습니다.C:\Users\rakslice\Documents\vboxsuspend\vboxsuspend.py
    • 완료를 선택하십시오.

이제 VirtualBox VM은 로그 아웃 / 재시작 / 종료시 일시 중단되어야합니다.

종료를 수행하는 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()