Ubuntu 11.10のVirtualbox内でWindows 7を実行しています。すべて正常に動作します。起動時に実行していますが、再起動に問題があります。
Sudo reboot now
と入力しても、仮想Windows 7の状態は保存されません。再起動後、virtualboxが起動しますが、実行中のWindowsの代わりにWindows 7のクラッシュブートメニューが表示され、Windowsが再度起動します。
ホストがリブートする前にインスタンスを安全に閉じるために、Ubuntuが仮想ボックスに何らかの信号を送信できるオプションはありますか?
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
または、 常にシャットダウン時に実行 のスクリプトを生成することもできます。
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/virtualbox
のacpibutton
が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つ小さな欠点が残っています。仮想マシンがまだ起動中で、ゲスト制御サービスが(仮想マシンで)起動していない場合、シャットダウンコマンドを受信しません。まれなケースですが...考えてみてください。
それがお役に立てば幸いです。
Sudo reboot
を使用すると、アプリケーションにそのような状況に対処する時間を与えることなく、プログラムを自動的に終了するkillシグナルが与えられます。これはバグではなく、常に同じように機能し、予想される動作です。
ユーザーメニューのshutdown
、reboot
、suspend
などのボタンを押すと、どのコマンドが与えられるかを見ることができる同様の質問があります。実行中のアプリケーションを使用してウィンドウを閉じようとするとき(その場合はSudo shutdown
アプローチよりも望ましい)。ご覧ください
this answerに従い、システムポリシーを変更して再起動します
これをreboot
に合理化することはできません。 AFAIK init.d
スクリプトは時間がかかりすぎるため機能しませんが、次のようにコマンドを実行できます。
VBoxManage controlvm <vm> savestate&&reboot
<vm>
は仮想マシンの名前です
以下を使用して、シャットダウン要求を仮想マシンに送信できます。
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サポートのない古いシステムをエミュレートしている場合は機能しません。