Using systemd to execute a script before system shutdown

shutdownsystemd

I wrote a script that suspends all my VirtualBox machines, and put a line in /etc/rc.local.shutdown, but it doesn't seem to work,

su - XX -c /XX

When I'm booting the next time, VirtualBox tells me the machine was Aborted, so the script wasn't executed. (Launching that script manually works for me)

P.S I already enabled shutdown.target

EDIT

The problem seems more complicated than I thought, in my .bashrc, if it's running on tty3, it executes startx, so when systemd decide to shutdown/reboot, it whould kill VBoxSVC process and other stuff when X Session dies.

I also tried to hack the source code of xfsm-shutdown-helper, make a fake systemctl that execute my script first, none of the above works.

Best Answer

If I understand you correctly, you want to suspend your VB machines before your bash session on tty3 terminates, or before your Xserver terminates.

I believe systemd is unaware of your running Xsession, because you start it from your .bashrc, so it will be difficult to tell systemd to suspend your VBs before it terminates your shell or your Xsession. You will have to find a place in the shutdown sequence which is "early enough", which might be difficult to find and semantically questionable, because it would mix "user stuff" with "system stuff"

The solutions may somewhat depend on how systemd terminates your processes, but the following should at least point in a good direction:

Before the shell terminates

suspendVB() {
        echo "suspending VBs"
        # put real code here
        exit
}

trap suspendVB EXIT

If you make this the rcfile of your bash (or add it to .bashrc), then the code in suspendVB() will be executed before the shell terminates. You can test this by running

bash --rcfile xxx

where the file xxx contains the code from above. This starts another shell inside your current shell, just for testing. When you then run a simple exit, you will see:

martin@beaureve:~$ exit
exit
suspending VBs
/home/martin >

and you are back in your original (login) shell.

You may have to find out how systemd actually terminates your login shells, and you may have to replace EXIT by some other signal(s). Lookup the trap command to find out more.

Note that When systemd kills your processes with "-9" (SIGKILL) then you will not be able to trap the termination, i.e. you're out of luck.

Before the Xsession terminates

Alternatively you may try a similar thing with your Xsession. This is essential in cases where systemd terminates your Xsession before it terminates your shells. You may want to insert a trap in one of the X startup files (e.g. .xinitrc) - lookup the man pages for startx and xinit to find out more.

If your startx file looks something like mine, then the xserver is started in foreground and you can alternatively simply place your suspend commands after the line where X is actually started (and not use traps at all):

xinit "$client" $clientargs -- "$server" $display $serverargs
retval=$?
echo " --- suspending VBs ---"

I put in the line saying "suspending VBs" and when I run startx -- vt8 I get a fullblows (kde) session on vt8 and only when I logout, the line "suspending VBs" appears on the screen.

Related Question