I need to run a software system that is intended to be installed as an appliance on a dedicated machine. In order to save energy, I plan to run the system on a VirtualBox VM instead.

The host is a standard Linux box with a SysV-Init system, the guest is a heavily modified Linux and I would prefer not to have to alter it further. VirtualBox is used in the OSE version.

I have already figured out how to start the VM when the host boots (Edit: this is done, as Nikhil mentioned below, through the command VBoxManager startvm), but how can I gracefully shut down the VM? Any script running on the host would need to wait until the guest has fully shut down.

Can anyone suggest how, for example, a service file doing this would have to look?

  • could you give the startup script to start virtual machine while booting
    – Beginner
    Sep 26, 2014 at 7:26

11 Answers 11


Have you tried acpipowerbutton from this command set?

VBoxManage controlvm        <uuid>|<name>

Edit after reading the comments:

You can use acpid or other acpi utilities to make it graceful. Also, can you provide more information about how do you shutdown the machine at the moment?

Plain shutdown wouldn't wait for unfinished jobs, a time delay may be too long.

I assume you aren't using a window manager so try this tool.

Just seen this daemon. You might find it useful.

  • Thanks for your reply and welcome to unix.stackexchange.com! However, I'm afraid your answer also does not address my issue: acpipowerbutton simulates pressing the power button on a real machine, but after issuing this command on the host, the VM would, again, take some time to shut down.
    – jstarek
    Jan 18, 2012 at 19:11
  • 5
    Sure. So you have to write a loop that checks whether the VM is still running. ACPI is exactly the same method I use in my scripts for this. vboxmanage list runningvms until your VM is gone.
    – Nils
    Jan 18, 2012 at 20:20
  • OK, while I think I'll settle for a management wrapper in practice, +50 to you for pointing to the initscript!
    – jstarek
    Jan 24, 2012 at 14:35

Rather than code this up yourself, consider using Vagrant, which is built to instantiate and control virtualbox instances. The documentation is excellent and I suggest that you check it out rather than attempting to roll your own.

The long and short of it is that you create a simple control file and then run vagrant up to start as many VirtualBox instances as you want. You can use vagrant ssh to log into the hosts and vagrant halt to shut the host down (without terminating). vagrant destroy will get rid of the instances.

It supports provisioning with puppet, Ansible or Chef and allows you to control most of the exposed VBox configuration settings.

  • 2
    I'm a fan of vagrant, but in this case, what on earth would you want it for? The OP is running an appliance, not building up their own system, so provisioning misses the point entirely. And why go and make a custom 'box' out of the appliance, just to use vagrant, when you'd basically be going via the process of building the system with virtualbox to do that?
    – mc0e
    Nov 24, 2014 at 17:09

I have similar application as you, with one difference: I need to restart system and recover from snapshot.

What you are interested in is headless-mode.

I have a few of such services so I use following script:


if [ -z "$1" ]; then
        echo "Usage: $0 VMNAME_or_UUID"
        exit 1
set -x
VBoxManage controlvm  "$1" poweroff  #enforce turnoff
VBoxManage snapshot   "$1" restorecurrent   #retore state
VBoxManage showvminfo "$1" | grep State   #display state to ensure
VBoxHeadless -s       "$1"  #run in headless mode in background

how can I gracefully shut down the VM?

IF you want to turn off VM gracefully, you have two options, depending on your application:

  • Emulate "shut-down button" or "sleep button" and prepare VM to react on it (to close gracefully)
    • VBoxManage controlvm <uuid>|<VMname> acpipowerbutton
    • VBoxManage controlvm <uuid>|<VMname> acpisleepbutton
  • Save VM state in order to restore afterwards
    • VBoxManage controlvm <uuid>|<VMname> savestate

TIPS: You might find useful:

  • VBoxManage list vms - list of available vms
  • rdesktop IP-ADDR:3389 or rdesktop-vrdp IP-ADDR:3389 - when you would like a GUI (even remotely) when you run in headless mode : VBoxHeadless -s <uuid>|<VMname>
  • VBoxManage startvm - start with GUI for local debugging

Related VirtualBox manual's chapter: Chapter 7. Remote virtual machines - Step by step: creating a virtual machine on a headless server

P.S. If you are interested in full featured already implemented solutions, OpenStack seems interesting choice.


Looking at VirtualBox VM management documentation at http://www.virtualbox.org/manual/ch08.html

For listing the VMs, use the command VBoxManage list vms

For starting the VM, use the command VBoxManage startvm


For controlling VM, use VBoxManage controlvm

The controlvm subcommand allows you to change the state of a virtual machine that is currently running. The following can be specified:

VBoxManage controlvm <vm> pause temporarily puts a virtual machine on hold, without changing its state for good. The VM window will be painted in gray to indicate that the VM is currently paused. (This is equivalent to selecting the "Pause" item in the "Machine" menu of the GUI.)

Use VBoxManage controlvm <vm> resume to undo a previous pause command. (This is equivalent to selecting the "Resume" item in the "Machine" menu of the GUI.)

VBoxManage controlvm <vm> reset has the same effect on a virtual machine as pressing the "Reset" button on a real computer: a cold reboot of the virtual machine, which will restart and boot the guest operating system again immediately. The state of the VM is not saved beforehand, and data may be lost. (This is equivalent to selecting the "Reset" item in the "Machine" menu of the GUI.)

VBoxManage controlvm <vm> poweroff has the same effect on a virtual machine as pulling the power cable on a real computer. Again, the state of the VM is not saved beforehand, and data may be lost. (This is equivalent to selecting the "Close" item in the "Machine" menu of the GUI or pressing the window's close button, and then selecting "Power off the machine" in the dialog.)

After this, the VM's state will be "Powered off".

  • Note that on some systems, it is vboxmanage (all lower case).
    – Arcege
    Jan 8, 2012 at 15:48
  • 2
    Thanks for your reply, but unfortunately, this does not address my issue: I need to gracefully shut down the guest, i.e. issue a "shutdown -h now" inside the guest and have the host wait until the guest has shut down completely. None of the VBoxManage controlvm subcommands do that.
    – jstarek
    Jan 8, 2012 at 16:20
  • You can make sure that by rechecking all the vms are down in the host before host goes down. If you need to control host from inside the guest, then virtualbox.org/manual/ch08.html#vboxmanage-guestcontrol but this may not give you what you are looking for. You should write a startup script like /etc/init.d/vboxvms-service script on host system, which upon start will make all vms on and upon stop, will make all the vms go down. Jan 8, 2012 at 16:39
  • VBoxManage controlvm savestate is another possibilty (at least google tells me), it saves the machines status and shuts it down cleanly, but still no way to force the host to wait.
    – Baarn
    Jan 8, 2012 at 20:53

For a systemd based system, you could try this.

Step #1: create a service file

Description=VBox Virtual Machine %i Service

ExecStart=/usr/bin/VBoxHeadless -s %i
ExecStop=/usr/bin/VBoxManage controlvm %i savestate


Step #2: Enable the service file

$ sudo systemctl enable vboxvmservice@vm_name.service


  • 1
    It is preferred to include an answer here and optionally provide links to more detailed information. Link targets disappear without notice, making your answer worthless.
    – Anthon
    Jun 3, 2013 at 11:53
  • Well, the problem is I cannot really copy the whole systemd file in link 1 here, or should I do this?
    – Jan Rüegg
    Jun 3, 2013 at 14:04
  • Well, unfortunately "link rot" is a huge problem in those cases... I think, for posterity, the following two lines catch the basic idea behind your Link: It's creating a service that uses VBoxHeadless -s %i to start and VBoxManage controlvm %i savestate to stop the VM.
    – jstarek
    Jun 5, 2013 at 19:03
  • Tried this in Debian Jessie, but it didn't work. Created user and group, set ownership of all files (including /dev/vbox*). But when the service starts, it cannot find the VM, even though the name is right. Will use the normal init script after all.
    – mivk
    Dec 9, 2015 at 18:36

How about to send the command via ssh from the host to the guest?

I am not sure if it works and if you can check the status of the machine afterwards or get something like an exit-status, but it should down clean atleast.

  • Good thought, but this would warrant that guest VM be reachable via network from the host, atleast the ssh port(22). Jan 8, 2012 at 17:30
  • Basically, this would work, the appliance can be reached in the entire LAN via its DNS entry. However, suppose I wrote a script that ssh'd into the appliance whenever the host goes down -- it would still have to block (pause) until the guest has shut down completely. This is precisely the point of my question: How can the script know when the guest is down, so that it can yield control flow back to SysV-Init and the host can continue to shut down?
    – jstarek
    Jan 8, 2012 at 19:35
  • 1
    Your comment assumes that everything will work smoothly on host system and not on guest system. What if power cable is plugged out on host system? Its a different discussion. Your SysV-init on host system will wait for the service script to stop the VMs as long as service script understands the logic to get the guest VMs off in a right way (exec shutdown on remote host or just power off through vbox interface) and then yield return the success or failure status back to console or init. Jan 8, 2012 at 20:02
  • 1
    Regarding: how script knows when the guest is down, try a simple check if the vm is on or off from VboxManager interface and if the guest is ssh'able. Also, put some monitoring on the host system which will perform whether the VM is available from Vboxmanager and its ssh'able on a timely basis. Jan 8, 2012 at 20:05

My solution: In this shellscript 'root' is the invoker, and 'theuser' is the owner of 'thevm'

I know the vms have ended when the output of the command VBoxManage list runningvms returns an empty string.

    su -c "VBoxHeadless --startvm thevm" -s /bin/bash theuser &
    # maybe another vbox command

    su -c "VBoxManage controlvm thevm acpipowerbutton" -s /bin/bash theuser
    # maybe another vbox command
    while [ "`su -c 'VBoxManage list runningvms' -s /bin/bash theuser`" != "" ]
        echo waiting for VMs to shutdown
        sleep 3

To start vm:

VBoxManage startvm VMNAME --type headless

To stop vm:

VBoxManage controlvm VMNAME savestate

List all running vm's:

VBoxManage list runningvms

I have a virtual machine to control incoming faxes and other tasks that I perform a snapshot on nightly. To ensure that I can port the vm to another piece of hardware, I use a Linux cron job to turn-off the vm at 3a.m. using the acpipowerbutton, wait until the shutdown is complete, delete the previous week's (7-days ago) snapshot, make a new snapshot, and power-up the vm to get ready for the day.

I have edited the script I use to make it generic from any vm. Of course, you can change the name of the script, but this is my current production candidate. This can be put in your /usr/local/bin. I used the .sh extension isn't required, it is just a little insurance so I don't accidentally kick-off the script and turn-off a vm that I didn't want to. I have not put in a check to verify that a vm name was input, if the script is invoked without adding a vm name to the script, you will just get a few screens of error messages.

    # snaptake.sh - take a snapshot of vm in virtualbox
    # snapshot is named by the dow (Mon, Tue, ...) vm name must have no spaces.
    # Push the virtual power button to shut-off and wait so many minutes to complete
    # You need to have your vm configured to shutdown when the power button is pressed.
    # This method gives a much more controlled turn-off than the "pull-the-plug" methods.
    # A snapshot made with the vm not running, makes it easier to port to a different
    # computer.
    # Syntax: snaptake.sh VBName
    #   where VBName is the name of the virtual machine.  There can be no spaces in the name.
    # This script first attempts to turn-off the virtual machine with the acpipowerbutton method.  The
    # vm must have been configured to turn-off when the power button is pressed.  
    #Then, the oldest snapshot with the name for the day of week (Mon, Tue, Wed ... )
    # is deleted.  The name is derived from the date function.  Then a new snaphot 
    # is taken, using the same day of week. Finally the vm is restarted. 
    VBoxManage controlvm $1 acpipowerbutton 
    # Wait until vm has stopped running, waiting a few seconds between checks to keep cpu use down
    while [ `vboxmanage list runningvms | grep -c \"$1\"` -gt 0 ]
      sleep 3
    # Now delete last week's snapshot and make a new snapshot, using the 'dow' (Mon, Tue, Wed .... )
    vboxmanage --nologo snapshot $1 delete `date '+%a'` 2>/dev/null
    # This might be unnecessary, I haven't verified yet whether the wait is required
    # or not for delete to complete.
    while [ `ps -ax  | grep /VBoxManage\ | grep \ $1\ | grep -c delete` -gt 0 ]
      sleep 3

    # Take the new snapshot, give it the name of the day of week (Mon, Tue, ... )
    vboxmanage --nologo snapshot $1 take `date '+%a'` 2>/dev/null
    # wait a few more seconds, the snapshot goes fast
    while [ `ps -ax  | grep /VBoxManage\ | grep \ $1\ | grep -c take` -gt 0 ]
      sleep 3

    # Uncomment following line to start the vm, comment it to keep the vm off
    DISPLAY=:0 VBoxManage startvm "$1" --type gui 2>/dev/null

This solution comes from ideas on this website and others and trial and error to get things working for my configuration. This script is running on an Ubuntu 20.04. I believe the syntax and functions I have used will operate only on the exact virtual machine named and not similarly named vm's.


Maybe this will help as part of the solution.

VBoxManage list runningvms | tr -s '\" {' '%{' | cut -d '%' -f3  | while read uuid; do
   VBoxManage controlvm $uuid savestate; 

Why don't you login to your guest and shutdown from there?

Unless you have a good reason for not installing sshd and accessing the VM really through VBox, I'd go for a script that just issues an ssh shutdown -h now. To be honest, I'd create a script for every machine that properly shuts it down and perform some checkups while at it.

Just pack an /etc/init.d/shutdown_vm script that call the other one from the host, the call will block until is ready. This process (as described) adds a linux dependency at the guest but removes the VBox dependency at the host.

Cutting to the chase: you don't need to access VBox to shutdown a machine, if you have some means of accessing it (i.e. ssh) then the OS will always have some means for that (turning it on, is different of course)

  • Two reasons: First, as stated in the original question, I did not want to alter the heavily modified guest OS if it wasn't really necessary. Secondly, and more importantly, this was intended to provide a clean way to automatically shut down all running VMs if the host was shut down.
    – jstarek
    Mar 4, 2014 at 13:31
  • @jstarek But you don't have to modify your guest OS if you don't want to (99.99% of the time you have some means to log in, or is this an exception). And exactly that's the idea, if the host goes down, the proper script will get called when changing runtime and this just logs to the guest and shut it down from "inside", which is what vagrant does anyways... before going "brute force" that is...
    – estani
    Mar 14, 2014 at 16:50

You must log in to answer this question.

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