systemd allows you to create and manage services in extremely powerful and flexible ways. This page will only cover the most basic uses; for full details, please see the systemd manual pages.
As a modern service manager, systemd builds on the concepts, knowledge and experience of previous and contemporary service managers such as daemontools, runit and nosh. If you've ever used any of these, you will probably find systemd's service management features to be easy and comfortable.
If your only experience is with System V init.d scripts, you may be confused at first. Init.d scripts use many ugly hacks (for example, PID files, and all of the infrastructure surrounding PID files) to work around the fundamental brokenness of sysv-rc. If you have grown accustomed to these hacks, you may first need to unlearn some bad habits.
Unit files
If you're creating a brand new unit file for your service, you must first come up with a name. The name you select must not collide with any existing service name, because your unit file will take precedence over any Debian default unit file with the same name. For the purposes of this page, we'll use the name myservice.
Create your service's unit file with the ".service" suffix in the /etc/systemd/system directory. In our example, we will be creating a /etc/systemd/system/myservice.service file.
Unit files use the ".INI" syntax, with section headers in square brackets, followed by variable declarations within that section, one per line. We'll need three sections: Unit, Service and Install. For now, don't worry about the separate meaning of each section. Just follow the examples to see which variables go in which section.
Service type
The first thing you must identify is what type of service you will be managing. systemd.service(5) lists the types: simple, forking, oneshot, dbus, notify or idle.
Most services should use the simple type, which means a program that runs in the foreground. If your service normally runs itself in the background, search the documentation to see if it has an option to disable that. Running in the foreground is preferred.
If you can't prevent the daemon from forking itself into the background, then you must use the forking type.
Also, decide whether you want systemd to restart (Restart=) your service when it exits. The default is no (which is different from daemontools). The other choices are always, on-success, on-failure, on-abnormal, on-watchdog or on-abort. You can even set a delay before systemd restarts it (with RestartSec=).
Environment setup
Some services require configuration of their environment, such as which user they run as (if not root), which directory they start in (if not /), environment variables, resource limits, etc. These variables are documented in systemd.exec(5).
WorkingDirectory= (change directory before executing processes)
RootDirectory= (chroot)
- User=
- Group=
- UMask=
- Environment= (variables)
- ... and many, many other options
Logging may also be configured here, if you need to use something other than systemd's native logging (accessible through journalctl(1)).
Service dependencies
For the purposes of this page, we'll assume that you want your service to start at boot time, and that you need it to wait for the network to be brought up first. The variables that control inter-service dependencies are documented in systemd.unit(5).
- After= (services that must be started before ours)
WantedBy= (basically "which run level")
Putting it together
For our basic service, which uses the network, and should be run every time we boot into "multi-user.target" or higher (i.e. all normal system boots, with or without a graphical Display Manager), we end up with a service unit file like this:
# Contents of /etc/systemd/system/myservice.service [Unit] Description=My Service After=network.target [Service] Type=simple Restart=always ExecStart=/usr/local/bin/myservice [Install] WantedBy=multi-user.target
Making it go
After creating or modifying any unit files, we must tell systemd that we want it to look for new things:
systemctl daemon-reload
Our new service should be recognized at this point, but it won't run yet. We need to do two more things. First, tell systemd to enable it, so that it will start every time we boot:
systemctl enable myservice.service
Second, start it now:
systemctl start myservice.service
Note that you don't get feedback from this command, because all it does it send a message to systemd telling it to start your service. The command you typed doesn't hang around to see what happens next. You may use systemctl status myservice.service (or systemctl status myservice) to check on your service, to make sure it seems OK.
Also note that systemctl status myservice gives more information if you run it as root, compared to running it as a normal user.