8

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?

5 Answers 5

6

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.

4

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

1
  • Has 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 for shutdown says "Once TIME has elapsed, shutdown sends a request to the init(8) daemon to bring the system down into the appropriate runlevel." Apr 20, 2013 at 19:49
4

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.

2
  • Works 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. Apr 20, 2013 at 22:44
  • I tried with both, native RDC and with RDC on top of VirtualBox. No such error. Probably related to virtualbox.org/ticket/8197
    – thomas
    Apr 29, 2013 at 18:40
2

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

1

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.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .