If you use Linux and you haven’t heard of systemd
yet, it won’t be long. With
most of the major distributions having adopted systemd already or planning to
adopt it within the next year ( RedHat, Debian, Ubuntu, Archlinux, etc…). So
since you can’t ignore and avoid it anymore, this blog post is going to discuss
what it is, why it’s an improvement on System V init, and how to interact with
it using systemctl
.
systemd
is a replacement init daemon for linux. The init daemon is the process
that the kernel launches on startup that manages starting everything else. At
it’s heart, it mainly is used for stopping/starting services and getting the
current status of a service.
It supports some awesome new kernel features, such as cgroups where every process
started by systemd gets it’s own cgroup
, so it’s easy to identify all the
processes associated with a service. It also allows systemd
to assign
a cgroup a max amount of memory, a higher CPU priority, Block I/O read/write
bandwidth and even some really nitty gritty values such as swappiness.
One of the things systemd excels at over System V init scripts is service
dependencies. If you aren’t familiar with how
/sbin/init
works, when it starts, it sets the runlevel
and first executes
all the K scripts in /etc/rcN.d/
(where N is the runlevel) with the stop
argument, followed by all the S scripts with the start argument. Everything is
done numerically, so if process foo needs to start before process bar, it would
be S02foo and S03bar. You can see how this could get unruly when you need to
insert process baz between foo and bar and there isn’t a number available. Now
you have to go about and renumber foo and bar, which means altering the RPM of
foo and bar to get baz to start at the right time. With systemd, we can specify
a service to require or even want (like require but if service doesn’t exist is
ignored) another service in the unit file. So when baz and bar 2.0 are
released, baz can require foo, and bar 2.0 can want baz.
Starting and stopping services with systemd is pretty simple. We use the
systemctl
command to interact with services. A service unit ends in .service
to distinguish between different types of systemd units. For this example,
we’ll stop/start/restart the httpd.service unit. To start our service, we run
systemctl start httpd.service
. Similarly, to stop the servce we run
systemctl stop httpd.service
. To restart, the command is:
systemctl restart httpd.service
.
Another benefit to systemd is monitoring of services. With System V, to get the status of a service, the init script needed to be written to support it. We get this “Out of the box” with systemd with all services. Here’s an example output of a stopped service:
sam@myvm:~$ sudo systemctl status -n 50 apache2.service
apache2.service - LSB: Start/stop apache2 web server
Loaded: loaded (/etc/init.d/apache2)
Active: inactive (dead)
CGroup: name=systemd:/system/apache2.service
And of a started service:
sam@myvm:~$ sudo systemctl status ssh.service
ssh.service - LSB: OpenBSD Secure Shell server
Loaded: loaded (/etc/init.d/ssh)
Active: active (running) since Fri, 13 Mar 2015 14:23:33 -0400; 3 days ago
CGroup: name=systemd:/system/ssh.service
└ 1183 /usr/sbin/sshd
Mar 16 22:04:52 myvm sshd[12496]: Accepted publickey for sam from 10.211.55.2 port 53061 ssh2
Mar 16 22:04:52 myvm sshd[12496]: pam_unix(sshd:session): session opened for user sam by (uid=0)
Mar 16 22:55:27 myvm sshd[12577]: Accepted publickey for sam from 10.211.55.2 port 53362 ssh2
Mar 16 22:55:27 myvm sshd[12577]: pam_unix(sshd:session): session opened for user sam by (uid=0)
Mar 16 23:18:48 myvm sshd[12593]: Accepted publickey for sam from 10.211.55.2 port 53766 ssh2
Mar 16 23:18:48 myvm sshd[12593]: pam_unix(sshd:session): session opened for user sam by (uid=0)
Mar 17 10:17:07 myvm sshd[18117]: Accepted publickey for sam from 10.211.55.2 port 52378 ssh2
Mar 17 10:17:07 myvm sshd[18117]: pam_unix(sshd:session): session opened for user sam by (uid=0)
Mar 17 10:45:42 myvm sshd[30694]: Accepted publickey for sam from 10.211.55.2 port 52716 ssh2
Mar 17 10:45:42 myvm sshd[30694]: pam_unix(sshd:session): session opened for user sam by (uid=0)
There’s a hidden gem in the status command above. Because systemd by default sends all stdout/stderr output to journalctl, we can get the most recent logs via the status command. If we want more, we can use the -n parameter to specify the number of lines of logs we want to see. In this case, we haven’t even created a systemd unit file. systemd is starting the old LSB init script without any new systemd features being setup in unit files.
This is the basic usage of systemd. In future blog posts we’ll look at some
more advanced features like writing your own unit script (to see an example of
how easy it is, see my blog post on Advanced Docker Networking with Pipework),
integrating with dbus, using other unit types like timers and taking advantage of
cgroups to control your processes resource usage. Until next time, enjoy
playing with systemd
.