Shutting down a VirtualBox VM automatically at log off

I use openSUSE 13.1 with KDE. If I log off when a VirtualBox VM is running, a message box pops up asking whether I want to save the machine state, send the shutdown signal or power off the machine. I do not want to press keys manually, instead of it I want to execute the command

VBoxManage controlvm <vm> savestate

The problem is I cannot find the right place to put the command. If I put it in a shutdown script in ~/.kde4/shutdown or even in an init script, the same message box pops up. I also tried to put the command in /usr/bin/startkde with the same result. How can I run the command before VirtualBox pops up the message box?

First create your script and then just symlink them to the correct kde directory.

"$HOME/.kde4/Autostart/"
"$HOME/.kde4/shutdown/"

This is also thesame when using

Systemsettings -> Startup and shutdown -> Autostart -> Scriptfile -> Add script 

You will also have an option to run your script at start or shutdown in KDE. :wink:
Of course the script needs to be executable…

I’ve already done it as could be seen from my first post. It results in a pop up window when I try to log off. By the way if I press the button in the pop up window I have described in my first post, then the VM is shut down but logging off is canceled. It is a bug in VirtualBox but my question is not about the bug, but how I can shut down the VM automatically.

Ok, let me give you some holding hands :slight_smile:

The startup script.

#!/usr/bin/env bash

exec >> ~/VBoxAutoStart.log 2>&1

printf '%s
' -----"$(date +%d-%b-%Y-%H:%M])"-----

vms=(foo bar)

for i in "${!vms@]}"; do
  VBoxManage startvm "${vms*}" --type gui
done

The savestate script.

#!/usr/bin/env bash

exec >> ~/VBoxAutoStart.log 2>&1

printf '%s
' -----"$(date +%d-%b-%Y-%H:%M])"-----

vms=(foo bar)

for i in "${!vms@]}"; do
  printf '%s
' "Saving machine ${vms*}"...
  VBoxManage controlvm "${vms*}" savestate
done

It is in ~/bin and you can name it to you own hearts content. Make it excutable. Like what i have posted before using the proper kde directories using system-settings.

Systemsettings -> Startup and shutdown -> Autostart -> Scriptfile -> Add script

You can always add/remove some vms inside the array in between the ( and ) separated by a space. My vms names are foo and bar in this case. Check the logs if you want too :slight_smile:
This is tested on 12.3 and 13.1 kde with VBox version 4.3+, so dunno what is wrong with your setup but It works like a charm on this side ;).***

One more thing you can replace the gui with other options such as headless and sdl too…

Thank you.

I changed your VM names to mine, placed the script in ~/bin and made a symlink to it from ~/.kde4/shutdown. My VM was running. I chose “Log out” from the host system menu and the same window I have seen previously popped up: SUSE Paste After I pressed OK button in the pop-up window, the VM state was saved, the VM was shut down and I saw a notification from KDE Workspace:

Logout canceled by ‘/usr/lib/virtualbox/VirtualBox’

~/VBoxAutoStart.log was not created because the mentioned above script had no chance to run.

This is tested on openSUSE 13.1, linux 3.11.10-11-desktop x86_64, KDE 4.11.5 and virtualbox 4.3.10-114.7.

So my question is still unanswered: How can I run the script before* VirtualBox pops up the message box?*

I have tried to reproduce your issues but so far i can’t. Does not seem to appear on this side. By the way if it matters i have the Oracle version of VBox and not from the suse repo, been a while since i have used that package. Also does it has the same issue on any vm not just windows? I have win7 also as a guest and so far no issues like yours.

Now to really answer the topic. Shutting down a VirtualBox VM automatically at log off regardless how they are started i.e. at boot, before log-in or manually started.

The script.

#!/usr/bin/env bash

# ******************************************************************************************** #
#                                                                                              #
#  Default Log everything to ~/VBoxAutoSave.log.(Change the value of LogFile to your liking.)  #
#                                                                                              #
# ******************************************************************************************** #

LogFile=~/VBoxAutoSave.log

if  $LogFile ]]; then
  exec > >(tee -a "$LogFile") 2>&1
fi

# ******************************************************************************************** #
#                                                                                              #
#    The date in between the dashes. (Change the value of date and dash to your liking :-).    #
#                                                                                              #
# ******************************************************************************************** #

Dash='---------------------------'
Date=#$(printf "%(%d-%b-%Y-%H:%M])T
" -1)

 printf '
%s
' "${Dash}${Date}${Dash}"
  
# ******************************************************************************************** #
#                                                                                              #
#  VBoxManage Functions. for more info on "command -p", see "help command" using your shell.   #
#                                                                                              #
# ******************************************************************************************** #

ListRunningVms() {
  command -p VBoxManage list runningvms
}

SaveRunningVms() {
  printf '%s
' "Saving machine '$RunningVmName' state..."
  command -p VBoxManage controlvm "$RunningUuid" savestate
}

# ******************************************************************************************** #
#                                                                                              #
#    Function to sanitize/extract the vmname and uuid using P.E. inside the stop function.     # 
#                                                                                              #
# ******************************************************************************************** #

ExtractVmNameUuid() {
  RunningUuid=${line##*"{"}
  RunningUuid=${RunningUuid%"}"*}
  RunningVmName=${line#*'"'}
  RunningVmName=${RunningVmName%'"'*}
}

# ******************************************************************************************** #
#                                                                                              #
#       Check for runningvms, If there is none found exit immediately without an error.        #
#                                                                                              #
# ******************************************************************************************** #

mapfile -u5 -t RunningVms 5< <(ListRunningVms)

(( ${#RunningVms@]} )) || { 
  echo 'No virtual machine runnning!'
  exit 0  
}

# ******************************************************************************************** #
#                                                                                              #
#   Finally Loop through all the runningvms and save the state. Set the exit status as well.   #
#                                                                                              #
# ******************************************************************************************** #

while read -u6 -r line; do 
  ExtractVmNameUuid 
  SaveRunningVms
done 6< <(ListRunningVms)

exit 0

# ============================================================================================ #
#                                                                                              #
#                                   >>> END OF SCRIPT <<<                                      #
#                                                                                              #
# ============================================================================================ #


Just do the same thing with that previous savestate script and symlink to autosave.

I have it in gist also you can run the following code below as a normal user. You can browse that link before you run curl on it though.

curl -s https://gist.githubusercontent.com/Jetchisel/c339976af08ea4f14b14/raw/f25e3e6cdcb471e2c6ae3f39153dcbc0f5d05dfb/VBoxAutoSave > ~/bin/VBoxAutoSave

chmod +x ~/bin/VBoxAutoSave

ln -sv ~/bin/VBoxAutoSave ~/.kde4/shutdown


Sorry about your log-out issues if i can’t help with that but you can try the Oracle package just to rule out the packaging/package issues though.

I use http://download.opensuse.org/repositories/Virtualization/openSUSE_13.1/ repository. Today VBox was updated there and it has now the same version as on the virtualbox.org, but this has not eliminated the problem.

I installed openSUSE 12.3 x86 in a new VM and included its name as the first in the VM list of your script.Now when I try to log out from the host I see a similar pop up window, but for this VM.

I also installed a clean hard drive into my PC, installed to it openSUSE 13.1 x86_64 with the default software (that is I changed nothing during installation), installed all updates, downloaded the virtualbox rpm from
https://www.virtualbox.org/wiki/Linux_Downloads
and installed it, built the kernel module and copied my VMs and your script to the disk. I checked that the script was registered. I started two VMs: linux and windows. After I tried to log out from the host, I saw the familiar pop up window.

And I tested it on a different host with openSUSE 12.3 x86, kernel 3.7.10-1.32-desktop, KDE 4.10.5 and VirtualBox 4.2.6-3.6.11. Alas, the result is the same.

Perhaps someone can give some feedback about this bug? Feedback folks!!! :), I for one do not have this issue. I only see that window when i try to close the main vbox vm by clicking the x button lol!

When I saw this thread I was intrigued…

Looking at this closely, there are a number of scripts that describe how to execute gracefully shutting down VBox guests either saving or not saving state, but I couldn’t seem to find any that describe the recommended way to do this when simply logging off.

So, I am curious whether you really meant when simply logging off or doing a complete Host shutdown or reboot?

As for the Guest shutdown script itself, I perused a number of scripts, they all do the same thing with more or less complexity… Apparently you need to invoke a list of running vms because VBManage does not understand wild cards or default to “everything” – You need to shutdown each Guest individually.

So, a list of running VMs has to be invoked, and then loop through that list first saving state and then shutting down (recommended acpi and not a hard shutdown).

I wonder if anyone really would want to shutdown Guests on merely log off, typically when logging off you want processes and apps to continue to run.

If, on the other hand you intend to shutdown or power off the Host, then you probably will want to invoke the script by modifing the systemd Unit files, here is one simple example
http://unix.stackexchange.com/questions/39226/how-to-run-a-script-with-systemd-right-before-shutdown

Don’t follow exactly what is described, though…
I’m guessing that the “delayed shutdown” service should be used instead of the regular shutdown Unit file…
You should copy the original Unit file to the location where you can make modifications to the file

cp /usr/lib/systemd/system/systemdshutdownd.service /etc/systemd/system/

Any copies of Unit files in the new location under /etc/systemd/ over-rides files which might be found in the original location, and you can create new custom Unit files here. If you want to undo your modifications, you only need to delete your copy to allow the original file to execute.

You can then add the line in your new copy with the ExecStop parameter pointing to your script.

Your script should then work on any shutdown/reboot regardless of Desktop or even running headless.

IMO,
TSU

Unfortunately I can’t opine for sure because the OP hasn’t described the popup message in detail (or posted a picture).

But, I’d guess that the problem is with permissions.
Running and administering virtual guests in general usually requires special permissions, eg either in a VBox group, under the root account or in a group with root access. Assuming this is also true of VBox running on an openSUSE Host(I’m not doing this), his default User permissions are inadequate.

If this is verified, then the solution should be pretty straightforward and one of the following can be implemented…

  • Add the User to the required security group
  • Execute the script on logoff with the correct permissions (but typically will require User interactive authorization, but only once)
  • If as I posted earlier the User really meant to shutdown or reboot the Host, then the Unit file modification I described would work.

TSU

ExecStop is not the only entry you need to put in that unit file that really is a case to case basis depending on the nature of your binary/executable/script or whatever :). Also comment out the DeafultDependencies if your binary/executable/script needs a before entry in that unit file.

If you are running the vms using the VirtualBox gui manager then that systemd solution will fail 100%, Your vms will be in the ‘aborted’ state, why? Vms are running with the gui option so you either need to save state of shutdown the guest before logging off or a shutdown of the host. Vms that are running headless should shutdown,savestate gracefully using that systemd unit file.
It is the same thing as starting the vms via a startup script, you cannot start the vms with the gui option not after the X server starts and you are logged-in ;).

I agree that the user must be in the vboxusers group. Also if the OP just want to keep vbox vms running while he logs out then tmux or screen might be a solution.

As for the script i have no comment on that the comments on the script should speak for itself…

One small correction folks.

if  $LogFile ]]; then
  exec > >(tee -a "$LogFile") 2>&1
fi

Missing the -e option since it is a file not a string variable :(.

if  **-e** $LogFile ]]; then
  exec > >(tee -a "$LogFile") 2>&1
fi

Any way see

help test

using your own shell.

If you haven’t found a solution yet i suggest you grab (if using the suse package) the vboxshell.py it is included in the vbox.org package you can test that.

/usr/lib/virtualbox/vboxshell.py <<EOF
save **foo**
EOF

Where foo is the name of your vm try that as your shutdown script inside ~/.kde4/shutdown just to test and see if that works.

Or with all your vms

/usr/lib/virtualbox/vboxshell.py <<EOF
foreachvm save
EOF

It is an interactive in nature so i just use a heredoc to in order to have it in a script. You can just

/usr/lib/virtualbox/vboxshell.py 

and type

help

for more options. It is a python script (with 3599 lines) by the way and it is GPL’d so you can extract that script from the vbox package itself if you are using the package from opensuse and put that in bin, also you can remove the .py extension if you like ;). I did tested it on a fresh 13.1 install and vbox.org package and it worked. I also have the pop-up window that you are describing about from the start. That script solved the issue. There is something about that python script that silenced that canceled log-out. It might be a feature or a bug but the python masters can prolly answer that or the vbox dev themselves rotfl!.

Thank you very much for telling about the script, it is interesting.

Unfortunately it does not solve the problem for my setup. I guess the problem originates in parallel execution in systemd, so which process is serviced first may depend on different things. That is why the same configuration runs differently on different computers. I think the only guaranteed way to get rid of this annoying dialog window is to hook logging out in KDE before it is serviced by systemd. I am sorry to say I have never developed any program in Linux (but only in Windows), so I have to read much before I can try to solve the problem this way. I have no time for it just now but maybe I’ll have time for it later on.