ホストの再起動時に仮想ボックスマシンを安全に閉じます


8

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

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

Ubuntuがホストを再起動する前にインスタンスを安全に閉じるために仮想ボックスに信号を送信できるオプションはありますか?

回答:


6

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

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


4

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

あなたが与えられたコマンドを参照することができます同様の質問があり、あなたは押すとshutdownrebootsuspend、ユーザメニュー上などのボタンは、そのような解決策は、実行中のアプリケーションとその好適でウィンドウを閉じようとするときに(何をすべきかを尋ねるべきあなたの場合)sudo shutdownアプローチへ。見てください


最近の再起動はより丁寧になりましたか?reboot12.10 のマニュアルページには、「-forceで呼び出された場合、またはランレベル0または6で呼び出された場合、このツールは、reboot(2)システムコール自体を呼び出し、システムを直接再起動します。それ以外の場合は、shutdown(8)ツールを呼び出します。適切な引数。 "; のマニュアルページにshutdownは、「TIMEが経過すると、shutdownはシステムを適切なランレベルにするためのリクエストをinit(8)デーモンに送信します。」
echristopherson

4

起動ジョブ、開始および停止スクリプトを含む、より洗練されたアプローチをお勧めします。例として、私は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:アップスタートマニュアルからもわかりにくい点:kill signalスタンザは5秒後に送信される信号を指定します。この例では、SIGTERM(デフォルト)からSIGCONT に設定していますが、5秒のタイムアウトを変更できませんでした。kill timeoutスタンザは、その後のタイムアウトを指定するSIGKILL1を変更することはできません合図-送信されます。したがって、改善は新しいスタンザ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

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

も表示されますがacpipowerbutton、未使用です。これは、信頼できる動作をしないためです。Windowsまたはさらに悪いことに複数のユーザーにログオンしている場合、Windowsは確認のシャットダウンダイアログを表示して、システムのシャットダウンを防止します。これも理由であるacpibuttonにおける/etc/default/virtualbox信頼性が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つ残っています。仮想マシンがまだ起動していて、ゲストコントロールサービスが(仮想マシンで)起動していない場合、シャットダウンコマンドは受信されません。まれなケース...それについて考えてください。

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


チャーム(Windows XPゲスト)のように機能しますが、スクリプトで指定されたユーザーとしてRDCを介してログインすると、ホスト側でがスローされ、その後ゲストが実行し続ける点が異なりVERR_INVALID_PARAMETERます。
echristopherson 2013

ネイティブRDCとVirtualBox上のRDCの両方を試してみました。そのようなエラーはありません。おそらくvirtualbox.org/ticket/8197に関連
tombert 2013

2

この回答に従って、再起動のシステムポリシーを変更します

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

VBoxManage controlvm <vm> savestate&&reboot

どこ<vm>仮想マシンの名前です。


1

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

VBoxManage controlvm <vm_name> acpipowerbutton

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

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

# 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サポートのない古いシステムをエミュレートしている場合も機能しません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.