DONG Yuxuan @ Jan 24, 2020
Introduce how to write an autostarted service for Unix with systemd.
Let’s say we have a simple Python script
#!/usr/bin/env python3 # Print the current time to /tmp/sysdt.log every 10 seconds from datetime import datetime from time import sleep while True: with open('/tmp/sysdt.log', 'a') as f: print(datetime.now(), file=f) sleep(10)
We want to make it a service, meaning run it as a autostarted daemon.
System services are managed by systemd in modern Linux. Every system service
has a corresponding unit file
Let’s write one for
sysdt.py and name it
[Unit] Description=sysdt [Service] Type=simple Restart=always ExecStart=/usr/bin/python3 /home/dongyx/sysdt.py [Install] WantedBy=multi-user.target
The service unit file consists of three sections,
Unit contains some descriptive infomation;
Service contains the
core infomation about which program to run, how to run, etc..
the infomation about when to lunch the service.
In our example, the
Service section contains three fields.
ExecStart is the
path and arguments to run. When we run
systemctl start sysdt in shell,
the content of
ExecStart will be executed.
We can also specify the
ExecStop to set what should happen if we run
systemctl stop sysdt. We don’t specify here thus it uses the default behaviour
SIGTERM to the process and all subprocesses of the service.
Type field specifies how
systemd check if the service is running.
The most common options are
If we set
systemd will think that the service is running
if the first process of the service is running. This is suitable for most
programs. If you run a long-time running program in a terminal and the
terminal blocks util the program is finished. The
simple option is what you
oneshot is for short-term running programs. The systemd considers the
service is still up after the process exits. For example, you have a very
simple program that appends the current time to a file then quits. You want to
make it autostarted to record boot times of the system.
oneshot is the right
forking option is for legacy daemons that call
fork to create
subprocesses then terminiate the parent process. For example, if you run
httpd -k start, Apache HTTPd will fork subprocesses to run in background and
terminate the parent process, thus the terminal dosen’t block. You could
apache2.service and it does use
Restart option sets whether the service should be restarted when the
service process exits, is killed, or a timeout is reached. We set it to
here. As its name implies,
systemd will always restart the program if it’s
We have configured how to run the program now. The last thing we need is making
it autostarted. We do this in the
WantedBy field of the
To explain it, we should understand the concept of targets.
A service is a
systemd unit, so does a target. However, unlike a service, a
unit represents a group of other units. You can put several srevices into a
target and start all the services by starting the target. The
WantedBy field sets which targets the service belongs to. Here we set it to
multi-user.target which is one of the preset targets of
systemd. While the
system boots, it has a boot target and
systemd will start it. For example, if
you boot the system into a graphical environment, the system is booted with
multi-user.target will also be executed. If you boot the system into a text
environment, the boot target is
be executed but
graphical.target will not because
require it. Besides
multi-user.target, there’re other
preset targets in Linux. For example,
rescue.target is for the system
administrator to fix booting issues thus it should lunch as less programs as
That’s why we set
multi-user.target. It means
starting the service when the system is normally booted (with graphical
environment or not, but is not booted into a rescue mode).