Shutting down all VirtualBox (vagrant) VMs in one easy to use bash command (that can be put into a bash file)

Solution 1:

For a scriptable control of Virtual Box machines we can make use of the VBoxManage commands:

  • List running machines (returns name and UUID):

    VBoxManage list runningvms
    
  • Stop running VMs by "hibernating" them (reommended to avoid data loss)

    VBoxManage controlvm <name|uuid> savestate
    
  • Poweroff running VMs (not recommended because we may lose data in the guest)

    VBoxManage controlvm <name|uuid> poweroff
    
  • Use ACPI in an ACPI-aware guest OS (preferable to poweroff for graceful shutdown of guests)

    VBoxManage controlvm <name|uuid> acpipowerbutton
    

Also see: How to safely shutdown Guest OS in VirtualBox using command line

Update from OP

Based on this selected correct answer below, I've added this bash script "$HOME/bin/stop-vagrant.sh". So now I have something that can safely begin a stop of all vagrant VMs that I might have turned on yet forgotten about in a session.

vboxmanage list runningvms | sed -r 's/.*\{(.*)\}/\1/' | xargs -L1 -I {} VBoxManage controlvm {} savestate

Command Explained:

vboxmanage list runningvms | -- gets a list of all running vms under VirtualBox

sed -r 's/.*\{(.*)\}/\1/' | -- strips the string down to id number

xargs -L1 -I {} VBoxManage controlvm {} savestate -- runs the save state command on each box that's open.

On xargs

  • -L1 - take one line at a time
  • -I {} - uses {} as a place holder for the next command

Solution 2:

The other answer is great for handling Virtualbox, but Vagrant features its own mechanisms for handling Virtual Machines, and as was mentioned in one of the comments, it supports more than just VirtualBox, just VMWare at the moment, but who knows later!

This seems to work for me:

vagrant global-status | awk '/running/{print $1}' | xargs -r -d '\n' -n 1 -- vagrant suspend

Note:

This works with Vagrant versions after 1.6, for older versions, you should probably upgrade, but if you can't, one of the other options which focuses on Virtualbox may be better.

Solution 3:

My mechanism for this:

vagrant global-status | grep virtualbox | cut -c 1-9 | while read line; do echo $line; vagrant halt $line; done;

  • global-status lists all boxes
  • filter that for lines containing virtualbox (Filters out the help text, will break if you're using some other provider)
  • Filter that to display only the first 9 characters (the global unique ID)
  • While we can still read a line from that input, read it as the variable $line then:
    • Print out that $line
    • run vagrant halt $line halting the vagrant for that global unique ID

This is better than the Virtualbox method above, because it'll run any vagrant-configured shutdown mechanisms too.