systemd: Writing and Enabling a Service

This section uses a BeagleBone Black Rev C, running a Debian Wheezy release from July 2015.

We have a whole category of BeagleBone tutorials. I found the specific image I installed on the elinux BeagleBoneBlack Debian page. Recent editions of the BeagleBone likely come with something very similar installed.

This section assumes that you are logged into your BBB as root.

Exploring systemd Basics

systemd takes a very different approach from the sysvinit scheme of organizing init scripts into directories by runlevel. Instead, it uses unit files to describe services that should run, along with other elements of the system configuration. These are organized into named targets, like multi-user.target and graphical.target.

You can list targets on the current system like so:

sudo systemctl list-units --type=target

Just running systemctl by itself will show you a list of all active units, including configuration for devices, services, filesystem mountpoints, timers, and sockets.

Mostly, systemd units are defined in various files in directories like /lib/systemd/system.

If you want to know the status of an existing service, you can use something like systemctl status foo.service - for example, let's check up on SSH:

sudo systemctl status ssh.service

You might notice something a bit odd here - this status report still mentions /etc/init.d/ssh. Isn't that a sysvinit thing? Well, yeah. What is happening is that the system we're on is still a hybrid between old-school and new-school init systems. systemd itself is actually capable of acting as a replacement (mostly) for sysvinit.

This all looks a little daunting, and there are a lot of concepts to untangle if you want to understand everything that's going on (your humble narrator is still quite a ways from this), but just configuring a new service is very little work.

Writing a Unit File

Let's reuse our example service, mouse.py. Run sudo nano /root/mouse.py, and paste the following code (notice that I've changed the port from 80 to 8888, so as not to step on the toes of other services already running on the BeagleBone):

#!/usr/bin/python
import SocketServer
from BaseHTTPServer import BaseHTTPRequestHandler

class MyHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header("Content-type", "text/plain")
        self.end_headers()
        self.wfile.write('<:3)~~~\n')

httpd = SocketServer.TCPServer(("", 8888), MyHandler)
httpd.serve_forever()

Then make sure this is executable with sudo chmod +x /root/mouse.py. Next, create /lib/systemd/system/mouselogger.service and use Nano to paste the following:

[Unit]
Description=Mouse Logging Service

[Service]
ExecStart=/root/mouse.py
StandardOutput=null

[Install]
WantedBy=multi-user.target
Alias=mouselogger.service

Now you can enable your new service:

sudo systemctl enable mouselogger.service
sudo systemctl start mouselogger.service

Did it work?

curl localhost:8888

Sure enough! As a last step, you should probably reboot and repeat this test to make sure.

Last updated on 2015-12-03 at 10.57.14 PM Published on 2015-09-01 at 04.02.25 PM