SYSTEMD

System and service manager

Introduction

System V

  • Legacy init system 
  • Based on runlevels:
    • 0. Halt
    • 1. Single User mode
    • 5. X Windows System
    • 6. Reboot

Example: Crond

#!/bin/bash

. /etc/rc.conf
. /etc/rc.d/functions

DAEMON=crond
ARGS=

[ -r /etc/conf.d/$DAEMON ] && . /etc/conf.d/$DAEMON

PID=$(get_pid $DAEMON)

case "$1" in
 start)
   stat_busy "Starting $DAEMON"
   [ -z "$PID" ] && $DAEMON $ARGS &>/dev/null
   if [ $? = 0 ]; then
     add_daemon $DAEMON
     stat_done
   else
     stat_fail
     exit 1
   fi
   ;;
 stop)
   stat_busy "Stopping $DAEMON"
   [ -n "$PID" ] && kill $PID &>/dev/null
   if [ $? = 0 ]; then
     rm_daemon $DAEMON
     stat_done
   else
     stat_fail
     exit 1
   fi
   ;;
 restart)
   $0 stop
   sleep 1
   $0 start
   ;;
 *)
   echo "usage: $0 {start|stop|restart}"  
esac

SysV issues

  • Synchronous and blocking
  • Tasks must be defined in advance

Upstart

Event based replacement for the traditional /sbin/init daemon

Feature Highlights:

  • Tasks and Services are started and stopped by events
  • Events are generated as tasks and services are started and stopped
  • Services may be respawned if they die unexpectedly
  • User services, which users can start and stop themselves

Upstart limitations

 

"a needs b" becomes"start a when b is started" plus "stop a when b is stopped".

The user has to manually translate the dependencies into simple event/action rules.

Hard to find why something started. D-bus !=> NM

Systemd

Goals:

  • start less, and more in parallel => D-bus socket
  • keeping PID 1 small => getting rid of shell scripts
  • keeping track of processes

Analyze boot time

systemd-analyze plot > boot.svg
graphical.target @4.464s
└─multi-user.target @4.464s
  └─docker.service @2.508s +1.956s
    └─network.target @2.507s
      └─wpa_supplicant.service @4.064s +11ms
        └─basic.target @2.234s
          └─sockets.target @2.234s
            └─docker.socket @2.228s +2ms
              └─sysinit.target @2.225s
                └─systemd-backlight@backlight:acpi_video0.service @3.148s +7ms
                  └─system-systemd\x2dbacklight.slice @3.148s
                    └─system.slice @194ms
                      └─-.slice @169ms

 

Analyze critical chain

systemd-analyze critical-chain

Power Management in Systemd

  1. systemctl reboot
  2. systemctl poweroff
  3. systemctl suspend
  4. systemctl hibernate
  5. systemctl hybrid-sleep

These commands can be run by unprivileged user

(if another user isn't logged in)

Systemd system management

# systemctl start unit

# systemctl stop unit

# systemctl restart unit

# systemctl reload unit

$ systemctl status unit

$ systemctl is-enabled unit

# systemctl enabled unit

# systemctl disable unit

# systemctl help unit

# systemctl daemon-reload

Unit Files

  1. .service
  2. .socket
  3. .device
  4. .mount
  5. .automount
  6. .swap
  7. .target
  8. .path
  9. .timer
  10. snapshot
  11. .slice
  12. .scope
  • Daemons and Services (init.d)
  • network/IPC socket (inetd)
  • Drivers (udev)
  • mountpoint (fstab)
  • Removable Media & Network Drives (autofs)
  • Swap files/partitions (fstab)
  • Group Units & Sync Point 
  • File system Changes (inotify)
  • Service Scheduling (crond)
  • Save state of all services
  • Set resource limitation (cgroup)
  • Group Arbitrary Processes (cgroup) 

Example redis

[Unit]
Description=Advanced key-value store
After=network.target

[Service]
Type=forking
ExecStart=/usr/bin/redis-server /etc/redis/redis.conf
ExecStop=/usr/bin/redis-cli shutdown
Restart=always
User=redis
Group=redis

[Install]
WantedBy=multi-user.target

Timers

[Unit]
Description=Rotate log files

[Service]
Type=oneshot
ExecStart=/usr/bin/logrotate /etc/logrotate.conf
Nice=19
IOSchedulingClass=best-effort
IOSchedulingPriority=7
[Unit]
Description=Daily rotation of log files

[Timer]
OnCalendar=daily
AccuracySec=12h
Persistent=true

Socket

[Unit]
Description=Docker Socket for the API
PartOf=docker.service

[Socket]
ListenStream=/var/run/docker.sock
SocketMode=0660
SocketUser=root
SocketGroup=docker

[Install]
WantedBy=sockets.target
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network.target docker.socket
Requires=docker.socket

[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd -H fd://
ExecReload=/bin/kill -s HUP $MAINPID
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
# Uncomment TasksMax if your systemd version supports it.
# Only systemd 226 and above support this version.
#TasksMax=infinity
TimeoutStartSec=0
# set delegate yes so that systemd does not reset the cgroups of docker containers
Delegate=yes
# kill only the docker process, not all processes in the cgroup
KillMode=process

[Install]
WantedBy=multi-user.target

Critics

  • Compatibility with other Unix systems
  • feature creep, not Unix like
  • monolithic 
  • Binary log

I don't actually have any particularly strong opinions on systemd itself. I've had issues with some of the core developers that I think are much too cavalier about bugs and compatibility, and I think some of the design details are insane (I dislike the binary logs, for example), but those are details, not big issues.

Linus Tovarlds

Adoption

  • Fedora (May 2011)
  • ArchLinux (October 2012)
  • Debian (April 2015)
  • Ubuntu (April 2015)

Questions

Sources

Systemd presentation

By Baptiste Desbiolles

Systemd presentation

  • 1,238