web-dev-qa-db-ja.com

ホストの再起動時にvirtualboxマシンを安全に閉じる

Ubuntu 11.10のVirtualbox内でWindows 7を実行しています。すべて正常に動作します。起動時に実行していますが、再起動に問題があります。

Sudo reboot nowと入力しても、仮想Windows 7の状態は保存されません。再起動後、virtualboxが起動しますが、実行中のWindowsの代わりにWindows 7のクラッシュブートメニューが表示され、Windowsが再度起動します。

ホストがリブートする前にインスタンスを安全に閉じるために、Ubuntuが仮想ボックスに何らかの信号を送信できるオプションはありますか?

8
takeshin

Virtual Boxの仮想マシンの実行中に本当にシャットダウンする必要がある場合は、シャットダウンプロセスが開始する前にマシンの状態を保存するコマンドを配置する手動シャットダウン用の独自のスクリプトを定義できます。

VBoxManage controlvm <name> savestate # <name> is the name of your VM
gnome-session-quit --power-off # this example displays the power-off dialog for >11.10

または、 常にシャットダウン時に実行 のスクリプトを生成することもできます。

6
Takkat

Upstartジョブ、startおよびstopスクリプトを含む、より洗練されたアプローチをお勧めします。例として、Windows XPを使用しています。ホームディレクトリではtombertを使用できるため、それに応じて変更する必要があります。 リブート、シャットダウン、電源ボタンの押し方)の利点があり、仮想マシンを適切に処理します

最初にupstartジョブを/etc/init/winxpvm.confに入れます:

description "WinXP VirtualBox job"
author "Thomas Perschak"

## 0: system halt
## 1: single-user mode
## 2: graphical multi-user plus networking
## 6: system reboot
start on started rc RUNLEVEL=[2]
stop on starting rc RUNLEVEL=[!2]

## upstart config
kill timeout 120
kill signal SIGCONT
Nice -10

## start WinXP VirtualBox
exec /home/tombert/scripts/winxpvm-start.sh

## stop WinXP VirtualBox
pre-stop exec /home/tombert/scripts/winxpvm-stop.sh

Upstartジョブは、ランレベル2(グラフィカルモード)で仮想マシンを起動し、私の場合、Niceで優先度を上げます。仮想マシンを適切にシャットダウンするには、kill signal SIGCONTステートメントを使用して、アップスタートの終了を「無効にする」必要があります。これにより、最初は仮想マシンが実行されたままになります(デフォルトのSIGTERMは回避されます)。 120秒後にSIGKILLが送信されます。代わりに、winxpvm-stop.shスクリプトを実行しています。

補足説明1:スタンザstart on started runlevel [2]およびstop on starting runlevel [!2]は機能しません。ジョブrcに特に言及する必要があります。

サイドノート2:upstartマニュアルからも混乱を招くもの:kill signalスタンザは、5秒後に送信されるシグナルを指定します。この例では、SIGTERM(デフォルト)からSIGCONTに設定しましたが、5秒のタイムアウトは変更できませんでした。 kill timeoutスタンザは、SIGKILLが送信されるまでのタイムアウトを指定します。これは変更できないことを示します。したがって、新しいスタンザterm signalおよびterm timeoutを定義することで改善されます。

ここで、起動スクリプトwinxpvm-start.sh:

#! /bin/bash -e

function dostart()
{
    echo -n "Running WinXP ... "
    vboxheadless --startvm WinXP
    echo "now closed"
}
export -f dostart

if [ $(whoami) != "tombert" ]; then
    su -c dostart tombert
else
    dostart
fi

すべての設定などはユーザーモードで行われるため(ログインはtombertであるため)、rootとして実行する場合でも、アカウントをtombert。もちろん、ユーザーはupstart構成で変更できますが、このソリューションでは、コンソールから「手動」で仮想マシンを起動/停止するオプションが残されています。

より興味深いのは、winxpvm-stop.shのシャットダウンスクリプトです。

#! /bin/bash

function dostop()
{
    ## check if WinXP is running
    vboxmanage showvminfo WinXP --machinereadable | grep -q 'VMState="running"' &> /dev/null
    if [ $? -ne 0 ]; then
        echo "WinXP not running"
        exit
    fi
    ## try gracefully shutdown
    echo -n "Shutting down WinXP ... "
    #vboxmanage controlvm WinXP acpipowerbutton
    vboxmanage guestcontrol WinXP execute --image "%SystemRoot%\system32\shutdown.exe" --username tombert --password <mypassword> --wait-exit -- "-s" "-f" "-t" "0" &> /dev/null
    ## check vm status
    INDEX=60
    while [ $INDEX -gt 0 ]; do
        echo -n "$INDEX "
        vboxmanage showvminfo WinXP --machinereadable | grep -q 'VMState="running"' &> /dev/null
        if [ $? -ne 0 ]; then
            echo "gracefully done"
            break
        fi
        sleep 1
        let INDEX+=-1
    done
    ## close forcefully
    if [ $INDEX -eq 0 ]; then
        vboxmanage controlvm WinXP poweroff &> /dev/null
        echo "forcefully done"
    fi
}
export -f dostop

if [ $(whoami) != "tombert" ]; then
    su -c dostop tombert
else
    dostop
fi

最初に、起動スクリプトと同じことを行います。ユーザーをルートからアカウントに変更していますtombert。次に、関数dostopを見てみましょう。最初に、仮想マシンが実行されているかどうかを確認しています。次に、guestcontrolを使用してWinXPに直接シャットダウンを送信することにより、「ソフトに」シャットダウンしようとしています。ここでは、WinXPアカウントの資格情報(私の場合はtombertとパスワード)を提供する必要があります。 Windows shutdownは、すべてのアプリケーションを正常に閉じ、オペレーティングシステムの電源を切ります(通常)。次に、showvminfoを使用して、仮想マシンの状態を継続的に確認します。これを1秒のタイムアウトで少なくとも60回(適切と思われるものは何でも)実行すると、仮想マシンが正常にシャットダウンするのに十分な時間を残すはずです。 showvminfoの呼び出しにも1秒よりも少し時間がかかることに注意してください(少なくとも私のコンピューターでは)。これにより、私の場合は約120秒になります。すべてが停止した場合、poweroffステートメントを使用して強制的にシャットダウンできます。

acpipowerbuttonも表示されるはずですが、未使用です。これは、信頼性の高い動作をしないためです。 Windowsにログオンしている場合、またはさらに悪いことに複数のユーザーがログオンしている場合、Windowsはシステムのシャットダウンを妨げる確認シャットダウンダイアログを表示します。これは、/etc/default/virtualboxacpibuttonが100%信頼性の高い動作をしない理由でもあります。また、poweroffは、長押しの電源ボタンと同じように、仮想マシンを強制的にシャットダウンします。したがって、これを空に設定するのが最善です。

/ etc/default/virtualboxからの抜粋:

# SHUTDOWN_USERS="foo bar"  
#   check for running VMs of user 'foo' and user 'bar'
#   'all' checks for all active users
# SHUTDOWN=poweroff
# SHUTDOWN=acpibutton
# SHUTDOWN=savestate
#   select one of these shutdown methods for running VMs
#   acpibutton and savestate causes the init script to wait
#   30 seconds for the VMs to shutdown
SHUTDOWN_USERS=""
SHUTDOWN=""

完璧にするには、電源ボタンの動作を変更する必要があります。

/etc/acpi/powerbtn.shからの抜粋:

#!/bin/sh
# /etc/acpi/powerbtn.sh
# Initiates a shutdown when the power putton has been
# pressed.

# @backup
# plain shutdown
/sbin/shutdown -h now "Power button pressed"

# fini
exit 0
...
...

1つ小さな欠点が残っています。仮想マシンがまだ起動中で、ゲスト制御サービスが(仮想マシンで)起動していない場合、シャットダウンコマンドを受信しません。まれなケースですが...考えてみてください。

それがお役に立てば幸いです。

4
tombert

Sudo rebootを使用すると、アプリケーションにそのような状況に対処する時間を与えることなく、プログラムを自動的に終了するkillシグナルが与えられます。これはバグではなく、常に同じように機能し、予想される動作です。

ユーザーメニューのshutdownrebootsuspendなどのボタンを押すと、どのコマンドが与えられるかを見ることができる同様の質問があります。実行中のアプリケーションを使用してウィンドウを閉じようとするとき(その場合はSudo shutdownアプローチよりも望ましい)。ご覧ください

4
Bruno Pereira

this answerに従い、システムポリシーを変更して再起動します

これをrebootに合理化することはできません。 AFAIK init.dスクリプトは時間がかかりすぎるため機能しませんが、次のようにコマンドを実行できます。

VBoxManage controlvm <vm> savestate&&reboot

<vm>は仮想マシンの名前です

2
Amith KK

以下を使用して、シャットダウン要求を仮想マシンに送信できます。

VBoxManage controlvm <vm_name> acpipowerbutton

ただし、initスクリプトでこれを行うと、シャットダウンが完了するまでスクリプトは終了しません。ループ内でlsofまたはfuserを使用してVMのドライブファイル(.vdi)をポーリングすることにより、それを検出できる場合があります。または、安価な回避策として、sleep 20で十分な場合があります。

以下は、initスクリプトのクローズブロックで現在使用しているものです。

# This always returns 0, even if an error is displayed!
su - "$DAEMONUSER" VBoxManage controlvm "$VMNAME" acpipowerbutton

# Wait until the disk file is no longer open...
for attempt in `seq 1 20`
do
    fuser "$VMDISKIMAGE" >/dev/null 2>&1 || break
    sleep 2
done

return 0    # A better script would return success/fail

定義したファイルの上部付近:

VMDISKIMAGE="/home/$DAEMONUSER/VirtualBox VMs/$VMNAME/$VMNAME.vdi"

これは実際にはVirtualBoxアプリ自体を閉じないかもしれませんが、VMがシャットダウンを完了するのを待ちます。また、仮想マシンがまだ起動プロセスにある場合(このフェーズ中に多くのオペレーティングシステムがパワーオフボタンを無視する場合)、またはACPIサポートのない古いシステムをエミュレートしている場合は機能しません。

1
joeytwiddle