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
-
systemctl reboot
-
systemctl poweroff
-
systemctl suspend
-
systemctl hibernate
-
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
-
.service
-
.socket
-
.device
-
.mount
-
.automount
-
.swap
-
.target
-
.path
-
.timer
- snapshot
-
.slice
-
.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