Getting Started With systemd on Debian Jessie
systemd may well be the future init system of choice for Linux. Here’s my experience of trying it out, presented as a hands-on tutorial.
You can find a great deal of blog posts about whether systemd or upstart will or should be the init system of the future for Linux. I wasn’t really finding many hands-on tutorials for Debian though, so here’s my experience of trying it out as a pretty casual Linux user. I am not an expert on the topic, so I recommend you don’t blindly follow these instructions on a production system.
I did this on a fresh minimal install of Debian Jessie, which is the Testing version of Debian at the time of writing. After installing Debian you want to install systemd by installing the packages systemd and systemd-sysv e. g. issuing:
apt-get install systemd systemd-sysv
Once systemd is installed and you reboot the system will automatically boot with systemd. Congratulations.
Starting, Stopping and Looking at Services
Throughout this article I am using nginx as an example of a daemon managed as a native systemd service. You may want to install nginx e. g. issuing
apt-get install nginx
as you follow through the examples, or replace the term with any suitable package of software you have installed.
systemd acts as a drop in replacement for the traditional init system. It executes the traditional shell scripts and manages their execution. So now you can and should actually manage all your services using the new system. The central tool to perform the aforementioned tasks is systemctl.
Checking the Status of Services
Running the command systemctl without parameters gives you a list of all known services and some extra information. systemd’s name for the stuff it manages is unit.
LOADED shows you whether the unit has been loaded correctly. This is a necessary condition for the unit being properly managed by systemd. ACTIVE shows you whether the unit is active. It does so in a generic terminology, which is the same for all units. In contrast SUB shows you a more specific piece of information: For example mounted for devices, running for a service like nginx.
To look at one specific service you issue:
systemctl status nginx
You can now, among other things, also see all the child processes of the nginx daemon. You don’t need root privileges to look at services.
Stopping, Starting, Restarting and Reloading Services
Starting and stopping services requires root privileges. To stop a service just issue:
systemctl stop nginx
In order to start a service issue:
systemctl start nginx
Neither command will complain if the unit is already in the desired state or return a status code other than 0.
In order to restart the service issue:
systemctl restart nginx
This will also start the unit if this is not already the case. As opposed to that:
systemctl try-restart nginx
will do nothing if the service is not started already. It will also not complain about this.
systemd also has a generic way to issue the soft reload that nginx and many other services support:
systemctl reload nginx
Understanding the Journal
In our example we’re managing a service which is started by a systemd service file. Let’s say we were managing a service started by a traditional init script. Where’s the output from the script? The systemctl commands will not write it to standard output. systemd writes the output of init scripts and all status messages generated by systemd to something called journal, a log database and syslog replacement. You can conveniently get the last relevant lines of output from the status command, again, issuing:
systemctl status nginx
At the time of writing cron was not converted to a systemd service, so you could check this out using:
systemctl status cron
As you can see, this is a convenient way to check recent events for both traditional and native services.
Here’s a caveat: You can only see those log entries if you run systemctl status with root privileges with the current configuration. The reason for this is that the journal is by default non-persistent (this will likely change sooner or later if systemd gets enabled by default in Jessie). Your systemd log-messages get thrown away at reboot. A side effect of this is that you need root privileges to see them.
Getting Debian Jessie to Use a Persistent Journal
Let’s change this behavior and have a persistent journal. Essentially, systemd is already configured to create a persistent journal. You just have to create the directory where it can store its log database (the following steps require root privileges).
It makes sense that this directory should be group-owned by the group systemd-journal.
chgrp systemd-journal /var/log/journal
And users which belong to this group should have full access to it:
chmod g+rwx /var/log/journal
We now have given systemd the ability to write its database to the directory.
It’s debatable what should be the optimal permissions on this directory. If you just want to be able to read the journal entries with your non-root user, add this user to the aforementioned group:
usermod -a -G systemd-journal <your username>
I think systemd needs to be restarted for the change to take effect, at least I had to reboot for it to work. I you like you can do this with systemd too:
Now you can query the journal using the utility journalctl — without root privileges. This utility gives you a pager-like view of recent events when called without parameters and allows all sorts of fancy querying. For example we can see the events for the unit nginx by issuing:
journalctl -u nginx
Thanks to reddit user fandingo and others for pointing out these issues concerning the journal in Debian Jessie to me.
Permanently Enabling or Disabling Services
This is pretty simple too. Issue:
systemctl disable nginx
This will disable the service — it should also work with services which are not in any way controlled by native systemd services files.
systemctl enable nginx
to enable a service.
You can still manually start or stop services even if they are enabled or disabled. It just means that they won’t start or stop at boot.
If you actually want to make it impossible that the service is started you can mask it:
systemctl mask nginx
This will link the unit to /dev/null, so it can’t be started.
Respectively, to unmask you unsurprisingly issue:
systemctl unmask nginx
Issuing disable, enable; mask or unmask will not start or stop the service. You need to do this separately.
Understanding Service Files
Completely understanding systemd is obviously way out of the scope of this article. Let’s, however, try to understand how services are declared in systemd. As you may know this is done declaratively in systemd, rather than in the style of a procedural shell script, as used to be the case in traditional init.
Here’s the nginx service file, as found in /lib/systemd/system/nginx.service on my system:
Description=A high performance web server and a reverse proxy server
ExecStartPre=/usr/sbin/nginx -t -q -g 'daemon on; master_process on;'
ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;'
ExecReload=/usr/sbin/nginx -g 'daemon on; master_process on;' -s reload
ExecStop=/usr/sbin/nginx -s quit
After declares that the service must be started only after the network target has been completed. Targets are similar to runlevels, but for reasons of flexibility the systemd developers have built in an extra layer of abstraction, as far as I understand. Basically what it says is: Only start this after the network is ready.
Type declares this service as forking, meaning that the service follows the traditional unix pattern of a daemon forking its process.
PIDFile is a file containing the process id of the service. This is no longer strictly necessary with systemd because systemd keeps track of all the processes started by the unit. However, according to the man page of systemd.service it is recommended to be used if the daemon forks because then “systemd can identify the main process of the daemon”.
I think the Exec commands are relatively obvious. These commands are executed when the respective tasks are issued, e. g. using systemctl.
Wanted means that if the service is enabled, then it is necessary to be started in order to complete the init of this target.
Exploring and using systemd on a basic level was painless and actually pretty convenient. I also think that service files will have a lot less boilerplate and error surface than traditional init files, once you get used to it. From a purely pragmatic perspective I would be looking forward to having systemd widely available as compared to the status quo.
systemd is a comprehensive package, you can use it to model complex dependencies between units, shutdown and restart your system, manage mount points (no more fstab needed). systemd also allows you to schedule jobs and thereby intends to replace a lot of cron functionality. I could continue this list.
Given this scope it’s hard to overstate systemd’s potential impact on Debian. It replaces a huge part of what we actually do with the OS.