Tuesday 5 July 2016

Easy Systemd Startup and Shutdown Scripts for Ubuntu 16.04 and Mint 18


Systemd is Here!

With the arrival of systemd in the buntu universe the old way of setting up startup and shutdown scripts is outdated.  In theory you can use the old SysVinit approach but my shutdown scripts were not executing so I decided to bite the bullet and learn how to do it with Systemd.

You'd think there would be a blog post saying, "do a, b, c and you're good" but I couldn't find one so after a bit of research here it is.  My main sources of information were an excellent article at CertDepot that explains the basics of systemd commands and file structure, and a discussion on stackexchange about running a script at shutdown.

Background. 

In systemd you create services to let systemd know what you want it to do.  The best place to store these is in the directory /etc/systemd/system.

You still need scripts that will perform the tasks you plan to run at startup and shutdown.  I created hidden scripts in my home directory.

How to do it.

First create the scripts you want to run at startup and/or shutdown.  I created .scopening_atstart and .scfullcopy_atend.

Then make sure that they are both executable by right clicking the file, selecting properties and making sure that, under permissions, you have ticked Allow executing file as a program.  You could also open a terminal and at the command line type chmod +x filename.


The two files I created populate and depopulate a ramdisk.  They also create a file in my home directory to prove that the service is working. They were of the form:

Then I opened /etc/systemd/system and created a file startup.service and a file save-ramdisk.service.  Obviously you can choose your own names and generic names could have included a startup file called johns_start.service and a shutdown file called johns_shutdown.service.  Just don't pick existing service names.  Their content was:

and

You can use the same service files, substituting the full path of your executable script for mine.

Finally for each one execute the command systemctl enable your_files_name (but without the suffix service) so my first one was systemctl enable startup

My shutdown script didn't work on my first exit possibly because I hadn't started the service before shutting down.  On the second shutdown, and then a reboot, it worked perfectly.  Additional useful commands include:

systemctl is-enabled startup
systemctl is-active startup
systemctl restart startup

More information can be found at the first reference above.





Power User Version

So, how about a master of the command line?

I will assume that you use sudo and your choice of editor, and that you are in your home directory.

You may execute commands directly from the systemd service files or call executable shell scripts.  Don Crissti discusses some startup commands at StackExchange.

Shell Scripts.  The file below assumes that you have created two executable shell scripts named .startup_commands and .shutdown_commands in your user's home directory and that your name is john (please change the user name).  A simple version of the startup script, that creates a file in your home directory, would be:

#!/bin/sh
#
date +%D' '%T > /home/john/startup_time


After creation you would have made the file executable:
chmod +x .startup_commands

Service Files.
# Create a file with the suffix service in the /etc/systemd/system directory
vim /etc/systemd/system/start_and_stop.service

# Copy the following content into the file, here called start_and_stop.service
# This version uses one file for startup & shutdown.   Separate files are show above.

[Unit]
Description=Run Scripts at Start and Stop

[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/home/john/.startup_commands
ExecStop=/home/john/.shutdown_commands

[Install]
WantedBy=multi-user.target


Commands
Enable the Service
# enable
systemctl enable start_and_stop


That's it.  After the first reboot, systemd will run .startup_commands as part of the multi-user start up process and .shutdown_commands when you shut down or reboot your system.





More Service File Options - Changing Targets


Above we have a service file that executes when multi-user starts up, one that executes when it shuts down, and a third that executes on it's start up and shutdown.  It is also possible to achieve finer distinctions.

The files above all use the open or close of the multi-user environment to initiate running the scripts.   The file below uses the beginning of four potential shutdown processes to initiate its scripts.

This was discussed in the second answer of this Stack Exchange post but I was unable to get it to run without adding the WantedBy line.

Again, edit the script in /etc/systemd/service/ and enable it using systemctl enable your_file_name.   When I changed the targets I used the systemclt disable file_name command and then re-enabled it which symlinked it to the target directories.

[Unit]
Description=Do something required
DefaultDependencies=no
Before=shutdown.target reboot.target halt.target
# This works because it is installed in the target and will be
#   executed before the target state is entered
# Also consider kexec.target

[Service]
Type=oneshot
ExecStart=/home/john/.my_script

[Install]
WantedBy=halt.target reboot.target shutdown.target