Safely close virtualbox machine on host reboot
Solution 1
In case you really need to shutdown while a virtual machine in Virtual Box is running you could define your own script for a manual shutdown where you place a command to save the machine state before the shutdown process starts:
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
Alternatively you could also generate a script that always runs at shutdown.
Solution 2
If you use sudo reboot
programs are given the kill signal ending them automatically without giving an application time to act on such situation. This is not a bug, it has always worked the same way and that is the expected behaviour.
There is a similar question where you can see which commands are given when you press the shutdown
, reboot
, suspend
, etc button on the user menu, such solution should ask you what to do when trying to close a window with a running application and its preferable (in your case) to the sudo shutdown
approach. Have a look
Solution 3
I would recommend a more sophisticated approach including an upstart job, a start and stop script. As example I am using Windows XP, as my home directory lets use tombert ... which you should change accordingly. It has the advantage of whatever you do (reboot, shutdown, pressing the power button) it handles your virtual machine nicely.
First the upstart job, put into /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
The upstart job starts the virtual machine in runlevel 2 (which is in graphical mode), and in my case it increases the priority with nice
. In order to nicely shutdown the virtual machine I need to "disable" the upstart termination using the kill signal SIGCONT
statement. This leaves the virtual machine running at first (avoiding the default SIGTERM
). After 120 seconds the SIGKILL
is send anyhow. Instead I am running the winxpvm-stop.sh
script.
Side-Note 1: The stanzas start on started runlevel [2]
and stop on starting runlevel [!2]
do not work. One has to specifically mention the job rc
.
Side-Note 2: What is confusing also from the upstart manual: The kill signal
stanza specifies the signal sent after 5 seconds. In this example I set it from SIGTERM
(default) to SIGCONT - but the 5 seconds timeout I was unable to change. The kill timeout
stanza specifies the timeout after which the SIGKILL
is sent - which signal one cannot change. An improvement therefore would be to define new stanzas term signal
and term timeout
.
Here the start script 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
Since all the settings etc. are done in user mode (as my login is tombert), even when run as root I change the account to tombert. The user of course could be changed in the upstart configuration but this solution leaves me the option to start/stop the virtual machine "by hand" from the console.
The more interesting is the shutdown script in 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
First I do the same as in the start script - I am changing the user from root to my account tombert. Now lets look at the function dostop
. First I am checking if the virtual machine is even running. Then I am trying to "softly" shutdown by sending a shutdown directly to WinXP using guestcontrol
. Here you must provide the credentials for the WinXP account, which in my case is tombert and a password. The Windows shutdown
will gracefully close all applications and power off the operating system (normally). Then lets check the virtual machine state continuously using showvminfo
. Doing this at least 60 times with 1 second timeout (do whatever you think appropiate is here) should leave the virtual machine enough time to shutdown gracefully. Note that the call to showvminfo
also takes a little bit less than a second (at least on my computer) so this gives it ~120 seconds in my case. If everything brakes we can forcefully shutdown using the poweroff
statement.
You also should see the acpipowerbutton
, but unused. This is because it does not work reliable. If you are logged on to Windows, or even worse multiple users, Windows will show a confirmation shutdown dialog preventing the system from shutdown. This is also the reason why the acpibutton
in the /etc/default/virtualbox
will not work 100% reliable. Also the poweroff
will forcefully shutdown the virtual machine - same as a long-press power button. Therefore it is best to set this to empty:
Excerpt from /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=""
To make it perfect you might want to change the power button behaviour:
Excerpt from /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
...
...
There is one little drawback left. When the virtual machine is still booting and the guest control service is not up (in the virtual machine) it will not receive the shutdown command. A rare case ... but think about it.
Thats it, hope it helps.
Solution 4
Follow this answer to change your system policy for rebooting
You can't streamline this into reboot
. AFAIK init.d
scripts will not work because it takes too much time, but you can run the command like this:
VBoxManage controlvm <vm> savestate&&reboot
where <vm>
is the name of the Virtual Machine
Solution 5
You can send a shutdown request to the virtual machine with:
VBoxManage controlvm <vm_name> acpipowerbutton
But if you do this in an init script, the script should not exit until the shutdown has completed. We may be able to detect that by polling the VM's drive file (.vdi) with lsof
or fuser
in a loop. Or as a cheap workaround, sleep 20
may suffice.
Here is what I am currently using in the close block of my init script:
# 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
Near the top of the file I defined:
VMDISKIMAGE="/home/$DAEMONUSER/VirtualBox VMs/$VMNAME/$VMNAME.vdi"
This may not actually close the VirtualBox app itself, but it does wait for the VM to complete shutdown. Also it does not work if the virtual machine is still in the process of booting up (many operating systems ignore the power-off button during this phase), or if you are emulating an old system with no ACPI support.
Related videos on Youtube
takeshin
Updated on September 18, 2022Comments
-
takeshin almost 2 years
I'm running Windows 7 inside Virtualbox on Ubuntu 11.10. Everything works fine. I'm running it at startup, but I have a problem with rebooting.
When I type
sudo reboot now
the state of the virtual Windows 7 isn't saved. After the reboot the virtualbox starts, but instead of the running Windows I get the Windows' 7 crash boot menu and the windows is booting again.Is there an option that Ubuntu could send some signal to the virtual box to safely close the instance before the host reboot?
-
echristopherson about 11 yearsHas reboot recently become more polite? The man page for
reboot
in 12.10 says "When called with --force or when in runlevel 0 or 6, this tool invokes the reboot(2) system call itself and directly reboots the system. Otherwise this simply invokes the shutdown(8) tool with the appropriate arguments."; and the man page forshutdown
says "Once TIME has elapsed, shutdown sends a request to the init(8) daemon to bring the system down into the appropriate runlevel." -
echristopherson about 11 yearsWorks like a charm (Windows XP guest), except it seems to throw out a
VERR_INVALID_PARAMETER
on the host side if I am logged in via RDC as the user given in the script, and subsequently the guest keeps running. -
tombert about 11 yearsI tried with both, native RDC and with RDC on top of VirtualBox. No such error. Probably related to virtualbox.org/ticket/8197