Systemd

2022-2-20 About 7 min

# Systemd

Systemd logo

Elk Unix systeem heeft een init systeem. Ons init systeem heeft PID 1 dat betekend dat dit het allereerste process is dat opstart bij het opstarten van ons systeem. Dit start dan ook meteen nadat de Kernel geboot is. In macOS is dit launchd, elke BSD heeft ook een eigen systeem. Ook zijn er verschillende init systemen die je op Linux kan gebuiken als OpenRC.

Als we kijken naar de keuzes van Ubuntu hebben we upstart sinds 2006 gebruikt en in 2014 vervangen door systemd. In andere Linux distributies zagen we ook een meer verschijden en vele distro specifieke configuraties terugkomen.

In meeste systemen bestonden services als complexe scripts die veel functionalteiten zelf deden, hierdoor was een eigen service schrijven niet zo handig.

In 2010 in Systemd gestart als idee om init systems beter te maken. Systemd probeerd complexiteit en overheid van verschillende scripts te verminderen. Het regelt veel zeld op basis van configuratiebestanden. Ook maakt systemd parallelisatie van het opstartproces mogelijk, oudere initstsemen werkten sequentieel in het uitvoeren van alle opstart scripts. Systemd probeert zoveel mogelijk gelijk te doen.

Systemd kunnen we zien als een allesomvattend init systeem. Het zal niet enkel zorgen voor onze achtergrondproccessen maar ook voor alles omliggend as netwerk instellen tot cron jobs draaien. Dit lijkt een mooie keuze te zijn maar het is ook de grootste kritiek, het doet namelijk de Unix filosofie teniet. In plaats van vele kleine tooltjes die elks iets heel goed doen te combineren gaat Systemd zelf alles in 1 codebase doen.

Voor ons gaat dit een voordeel bieden dat we veel informatie over onze server in 1 plek gaan kunnen vinden!

# Structuur

De onderstaande structuur komt van Tizen, maar geeft een mooi overzicht van de verschillende componenten van Systemd. Systemd compomenten in Tizen

We zien een paar grote groepen:

  • Utilities dit zijn de tooltjes die wij gaan gebruiken om alles aan te sturen
  • Daemons zijn achtergrondproccessen van Systemd zelf die alles regelen, deze spreken we aan met onze utilities
  • Targets zijn delen van het systeem die gestart moeten worden. Wij gaan deze gebruiken in onze services.
  • Core en Libraries zijn de onderliggende basis van Systemd.

# Gebruik

Systemd is terugtevinden in de grote meerderheid van alle Linux distributies, velen hebben rond het jaar 2015 Systemd geadopteerd. Er zijn ook een aantal Linux distributies die specifiek gemaakt zijn voor geen Systemd te hebben zoals Devuan. Hieronder is een lijst van grote Linux distribities die Systemd gebruiken volgens Wikipedia:

systemd in Linux distros

# Systemd voor Linux Servers

Wat betekend dit nu voor ons? Doorheen de cursus hebben we overal al systemctl gebruikt. We bekijken dit nu in meer detail!

We hebben 2 commando's die we veel gaan gebruiken

  • systemctl dit commando gaat alles van Systemd op onze server uitvoeren.
  • journalctl dit commando gaat alle logs van Systemd lezen en besturen.

note

In vele tutorials op het internet ga je het oude service commando tegenkomen. Dit commando dateert van voor Systemd maar is zo vaak gebruikt dan Ubuntu een alias instelt dat deze commando's gaat doorsturen naar Systemd.

Gebruik hiervan is afgeraden, Linux distributies die progresiever zijn (zoals Flatcar Linux) hebben deze alias niet (meer).

# Installatie

# Ik laat deze titel hier om een punt te maken
# Systemd staat al geĂŻnstalleerd
# het heeft je server net opgestart
1
2
3

# Gebruik

We gaan verschillende utilities gebruiken in de volgende delen. Maar waar komen deze rare namen als systemctl vandaan? Het is een recente trend in de Linux/Server wereld om een achtergrondprocces te hebben, traditioneel eindigend op d van daemon. Kijk naar httpd en sshd. Deze aansturen doen we via CLI (command line interface) tools die vaak eindigen op ctl van control. Voorbeelden zijn bluetoothctl, kubectl en systemctl.

# systemctl

We gaan systemctl gebruiken om alle informatie van Systemd op onze server te lezen.

Eerst gaan we bekijken wat er nu eigenlijk draait in systemd?

sudo systemctl list-units
1

We krijgen een enorme lijst aan alles wat op ons systeem draait. (Je kan deze verlaren door op q te drukken) We zien niet enkel onze services maar meer units. Een unit is een component dat in systemd draait, je herkent het type door hun bestandsextensie. We bekijken er een paar:

  • .device dit zijn alle aangesloten devices (ook virtueel)
  • .mount dit zijn alle mountpoints van bestandssystemen
  • .service dit zijn alle services
  • .socket dit zijn alle netwerksockets
  • .timer dit zijn alle timers (vergelijkbaar met Cron jobs)

In ons vak focussen we ons vooral op alle services, we kunnen deze filteren met een simpele grep:

sudo systemctl list-units | grep .service
1

# Services

Services zijn achtergrondprocessen die wij gaan configureren op onze server. Ze dienen voornamelijk om onze server software te laten draaien. We hebben al een service op onze Linux server staan, namelijk nginx.

Willen we alles weten over de status van NGINX? Dan kunnen we het commando systemctl status gebruiken. nginx.service is het bestand waar de service zich bevindt.

sudo systemctl status nginx.service
1

Systemctl gaat ook herkennen dat nginx een service is en we kunnen het ook korter schrijven:

sudo systemctl status nginx
1

nginx.service is een file die we meekregen in de installatie van NGINX. We kunnen dit bekijken met systemctl cat

sudo systemctl cat nginx
1
$ systemctl cat nginx.service
# /lib/systemd/system/nginx.service
# Stop dance for nginx
# =======================
#
# ExecStop sends SIGSTOP (graceful stop) to the nginx process.
# If, after 5s (--retry QUIT/5) nginx is still running, systemd takes control
# and sends SIGTERM (fast shutdown) to the main process.
# After another 5s (TimeoutStopSec=5), and if nginx is alive, systemd sends
# SIGKILL to all the remaining processes in the process group (KillMode=mixed).
#
# nginx signals reference doc:
# http://nginx.org/en/docs/control.html
#
[Unit]
Description=A high performance web server and a reverse proxy server
Documentation=man:nginx(8)
After=network.target

[Service]
Type=forking
PIDFile=/run/nginx.pid
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=-/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid
TimeoutStopSec=5
KillMode=mixed

[Install]
WantedBy=multi-user.target
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

Hiermee zien we alle congiguratie opties van de service. We bekijken de deelcomponenten later als we zelf een scrhijven.

We kunnen deze achtergrond service ook stoppen en starten:

sudo systemctl start nginx.service
sudo systemctl stop nginx.service
1
2

Of we combineren het met 1 commando:

sudo systemctl restart nginx.service
1

NGINX ondersteunt ook het "live reloaden" van configuratie, hier kunnen we dit doen:

sudo systemctl reload nginx.service
1

Hebben we echt problemen met NGINX? Dan hebben we de noodoplossing kill dit gaat de service killen in de process list.

sudo systemctl kill nginx.service # noodrem, do not use
1

We kunnen ook het automatisch opstarten van onze service besturen met Systemd. Met systemctl enable kunnen we de service automatisch opstarten bij het opstarten van de server. Met systemctl disable kunnen we de service uitschakelen.

sudo systemctl enable nginx.service
sudo systemctl disable nginx.service
1
2

# Eigen service

In de cursus gaan we vaak via onze apt installatie al een Systemd service meekrijgen. Echter in de praktijk moeten we vaak eigen services gaan schrijven voor interne applicaties. We gaan hier simple-service als voorbeeld gebruiken. Dit is een kleine webserver die ons op poort 8080 een webpagina gaat geven.

Voor we een service kunnen scrhijven hebben we onze binary nodig. Deze kunnen we downloaden van GitHub met wget en daarna uitpakken en installeren:

wget https://github.com/meyskens/simple-service/releases/download/v1.0.0/simple-service_1.0.0_linux_amd64.tar.gz
tar xzf simple-service_1.0.0_linux_amd64.tar.gz
sudo mv simple-service /usr/local/bin/simple-service
1
2
3

Meeste configuratie van systemd is te vinden in /etc/systemd/, de map system hier staan heel wat services. We gaan hier een service schrijven voor onze simple-service:

sudo nano /etc/systemd/system/mijn-service.service
1

Hierin plakken we de volgende configuratie:

[Unit]
Description=Mijn Coole Server
After=network.target
[Service]
ExecStart=/usr/local/bin/simple-service
Restart=on-failure
RestartSec=10s
[Install]
WantedBy=multi-user.target
1
2
3
4
5
6
7
8
9

We zien 3 delen:

  • [Unit] geeft alle informatie weer over deze Systemd unit.
    • Description is een beschrijving van de service
    • After geeft weer wat de service moet starten na de network.target, dus wanneer de server een netwerk verbinding heeft.
  • [Service] geeft dat dit een service en verteld ook wat te doen
    • ExecStart is het pad naar de binary om uit te voeren
    • Restart verteld wanneer Systemd de service moet herstarten. on-failure zorgt ervoor dat de service herstart als de binary een fout code geeft.
    • RestartSec is de tijd in seconden dat de service moet wachten voor een restart
  • [Install] geeft alle informatie weer voor de Systemd installatie.
    • WantedBy geeft weer wat de service moet worden gestart in de targer multi-user, dit draait op alle Linux systemen. Anders start de service niet tenzij een systeem component onze service als dependency heeft.

note

Er zijn enorm veel opties in Systemd units. We bespreken deze niet allemaal in de cursus. Hieronder zie je een aantal referenties die je kan raadplegen:

Nu we onze unit file hebben aangemaakt moeten we Systemd vragen deze opnieuw te laden. Dit doen we met:

sudo systemctl daemon-reload
1

Dit commando moeten we bij elke aanpassing aan een Systemd unit draaien.

Nu we de service hebben aangemaakt kunnen we deze enablen:

sudo systemctl enable mijn-service.service
1

En we starten de service met:

sudo systemctl start mijn-service.service
1

Zoals altijd bekijken we ook even de status:

sudo systemctl status mijn-service.service
1

En ten slotte kijken we ook even naar de output:

curl http://localhost:8080
1

# journalctl

We hebben al eens kort naar logging gekeken eerder in de cursus. Vandaag vinden we op twee plaatsen logs terug (3 als je systlog nog meeteld) op onze Linux server.

  • Applicatie specifieke logfiles, meestal in /var/log/
  • Journals: deze logfiles zijn geschreven door de systemd daemon van het systeem en services.

Applicatie specifieke logging werd vaak gebruikt maar vereist veel werk van de server code zelf. De server (zoals NGINX) is verantwoordelijk voor het schrijven van logging, maar ook voor het verwijderen van oude logfiles. Ook worden oudere logs vaak gecompressed voor schijfruimte te besparen. Meeste van deze files zijn te vinden in /var/log/.

In dit hoofdstuk zullen we vooral de Journals bekijken. Deze worden beheerd door de systemd daemon. Onze services moeten enkel maar simpele logs sturen naar de standard output/error (opens new window) en Systemd regeld alles voor ons. Het zal ze opslagen, archiveren en verwijderen wanneer nodig.

# Bekijken van logs

Logs kunnen we gaam bekijken met journalctl.

sudo journalctl
1

Dit geeft ons ALLE logs van het systeem weer... nu is dat iets te veel om nuttig te zijn.

Met de optie -u bekijken we de logs van een specifieke Systemd unit:

sudo journalctl -u mijn-service
1

We krijgen hier alle logs van onze applicatie zelf maar ook van Systemd over onze service. Probeer deze maar eens te herstarten!

We kunnen ook live onze logs "followen" met -f.

sudo journalctl -u mijn-service -f
1

Deze logs zijn een beetje saai, we stoppen ze met Ctrl+C.

We nemen even ssh als voorbeeld:

sudo journalctl -u ssh -f
1

Open nu een 2de termimal en log in op je server, je merkt op dat je de login live kan volgen!

# Log housekeeping

Logs nemen na een tijdje wel wat ruimte in, zo heeft mijn Linux laptop op dit moment 4GB aan logfiles, en ik draai nog niet eens een server!

Journalctl kan ons alle informatie geven met:

sudo journalctl --disk-usage
1

We kunnen dit gaan opruimen met:

sudo journalctl --vacuum-size=1G
1

Dit commando geeft Journald de opdracht de logs te beperken tot 1GB. Het blijft wel rekening houden met een minimale opslag van log files. Op onze niewe server gaat het weinig uitmaken.

We kunnen ook vragen om oude log files te verwijderen die ouder zijn dan een jaar:

sudo journalctl --vacuum-time=1years
1

Deze acties zijn manueel uit te voeren, je kan de ook aanpassen in /etc/systemd/journald.conf

We hebben verschillende opties:

  • SystemMaxUse= is de maximale grootte van de systeem logfiles op de schijf
  • SystemMaxFileSize= is de maximale grootte van 1 logfile op de schijf
  • RuntimeMaxUse= is de maximale grootte van de runtime logfiles op volitile media (geheugen)
  • RuntimeMaxFileSize= is de maximale grootte van 1 logfile op volitile media

Voorlopig zijn we nog blij met de standaard waarden!

Last update: February 20, 2022 14:05