Inmiddels alweer bijna tien jaar geleden werd systemd geïntroduceerd in Linux als de “manager van alles”. In het begin ging dat niet zonder discussie, maar inmiddels is systemd geen onderwerp van discussie meer. Tijd dus om eens een balans op te maken en te kijken naar de manier waarop systemd het werken met Linux veranderd heeft [Sander van Vugt]

Om tot een volledig werkend besturingssysteem te komen, moet een aantal stappen doorlopen worden. Het begint allemaal met de boot loader, in de meeste gevallen is dat GRUB2. Deze is verantwoordelijk voor het laden van de kernel en het initramfs, respectievelijk het hart van het besturingssysteem en het onderdeel waardoor de meeste drivers geladen worden. Als de kernel in initramfs eenmaal geladen zijn, roepen deze PID 1 aan. Voor comptabiliteit met vroegere versies van Linux roept de kernel nog steeds init aan, maar op de meeste distributies is het init proces gelinkt naar systemd. Systemd is dus PID 1 en als dusdanig daadwerkelijk de manager van alles.

De zaken die door systemd beheerd worden, bestaan uit verschillende typen. Al deze zaken worden aangeduid als units, en zoals gezegd zijn er verschillende soorten units. Het begint allemaal met de udev units, die zorgen voor de aansturing van hardware, daarnaast zijn er mount units, die zorg dragen voor het mounten van alles wat er maar gemount moet worden. Voor veel gebruikers het meest belangrijke unit type echter is de service. Dit type zorgt ervoor dat alle services gestart kunnen worden. Voor een volledig overzicht van alle units die momenteel in gebruik zijn, gebruik je de opdracht systemctl list-units. En als je alleen een lijst wilt hebben van alle unit types, gebruik je de opdracht systemctl -t help.

Beheer van services

Achter elk type unit is er een configuratiebestand. De eenvoudigste wijze om de configuratiebestanden te bekijken, is door middel van de opdracht systemctl cat, gebruik bijvoorbeeld systemctl cat sshd.service om te bekijken wat er precies gebeurt om de SSH service te beheren.

 

[sander@groudon ~]$ systemctl cat sshd.service

# /usr/lib/systemd/system/sshd.service

[Unit]

Description=OpenSSH server daemon

Documentation=man:sshd(8) man:sshd_config(5)

After=network.target sshd-keygen.target

Wants=sshd-keygen.target


[Service]

Type=notify

EnvironmentFile=-/etc/sysconfig/sshd

ExecStart=/usr/sbin/sshd -D $OPTIONS

ExecReload=/bin/kill -HUP $MAINPID

KillMode=process

Restart=on-failure

RestartSec=42s



[Install]

WantedBy=multi-user.target

 

Listing 1: Uitvoer van systemctl cat sshd.service.

In het voorgaande voorbeeld van het sshd.service bestand, zie je dat in dit bestand drie secties bestaan. Om te beginnen geeft de [Unit] sectie algemene informatie weer, maar definieert het ook de afhankelijkheidsrelaties. De regel After= geeft aan dat deze unit gestart moet worden nadat de genoemde network.target en sshd-keygen.target gestart zijn. De regel Wants= definieert een afhankelijkheid naar sshd-keygen.target.

Het tweede en belangrijkste onderdeel van de unit file is de [Service] sectie. Hierin vind je parameters die bepalen welk commando precies uitgevoerd moet worden. Ook zie je dat er een bestand met omgevingsvariabelen meegenomen wordt. Dat is handig, want dit bestand zorgt dat je systeem-specifieke omgevingsvariabelen niet in het Unit file zelf hoeft op te nemen. Ook interessant is de regel RestartSec=42s, die ervoor zorgt dat als er iets gebeurt met deze unit, hij automatisch opnieuw gestart zal worden.

In de [Install] sectie ten slotte wordt aangegeven hoe deze unit gestart moet worden. In dit geval gebeurt dat door de unit toe te voegen aan de multi-user.target, waarover later meer.

Om systemd units te beheren – ongeacht het type – is er een aantal opdrachten dat behoort tot je standaardgereedschap. Hieronder een overzicht, waarin we sshd.service als voorbeeld gebruiken. Als je de voorbeelden uit wilt proberen, moet je er op Ubuntu wel eerst voor zorgen dat de service ook geïnstalleerd is. Dit doe je met sudo apt install openssh-server. De meest uitvoerde opdracht is waarschijnlijk systemctl status sshd.service: dit laat de status van de service zien – zie listing 2 voor een voorbeeld.

In de uitvoer van systemctl status is er een aantal zaken dat opvalt. Als meest belangrijke zie je dat de service Active is, en momenteel dus zijn diensten aanbiedt. Je ziet ook met welk proces ID dat gebeurt (869) en zelfs hoeveel geheugen het proces daarvoor gebruikt. In de regel die begint met Loaded, wordt aangegeven dat het bestand /usr/lib/systemd/system/sshd.service geladen is, en hier zie je dus het exacte bestand dat gebruikt wordt door systemd. Ook heel prettig zijn de regels aan het einde van de uitvoer. Hierin zie je meldingen die recentelijk door het proces gelogd zijn. Systemd komt namelijk met een geintegreerde log manager in de vorm van systemd-journald, en hierdoor hoef je je nooit meer af te vragen in welk logbestand informatie nou precies is weggeschreven.

[sander@groudon ~]$ systemctl status sshd
  • sshd.service - OpenSSH server daemon
     Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; vendor pre>

     Active: active (running) since Wed 2021-02-24 09:09:26 CET; 1 weeks 3 day>

       Docs: man:sshd(8)

             man:sshd_config(5)

   Main PID: 869 (sshd)

      Tasks: 1 (limit: 76948)

     Memory: 5.5M

        CPU: 384ms

     CGroup: /system.slice/sshd.service

             └─869 sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups


Mar 04 11:11:35 groudon.example.com sshd[46924]: Accepted password for sander >

Mar 04 11:11:35 groudon.example.com sshd[46924]: pam_unix(sshd:session): sessi>

Listing 2: Uitvoer van systemctl status sshd.service.

Voor het alledaagse beheer van unit files wordt een aantal opdrachten gebruikt:

  • sudo systemctl start sshd.service: zorgt ervoor dat de unit nu gestart wordt
  • sudo systemctl enable sshd.service: zorgt dat de service wordt toegevoegd aan de default target (zie later) zodat hij automatisch gestart wordt als je computer gestart wrodt
  • sudo systemctl enable –now sshd.service: hiermee zorg je dat de service gemarkeerd wordt voor automatisch opstarten, en daarnaast ook nu gestart wordt
  • sudo systemctl stop sshd.service: stopt de service
  • sudo systemctl disable –now sshd.service: start de service niet langer automatisch op en stopt hem ook nu meteen.

Werken met Targets

Wanneer je Linux systeem opstart, moet er van alles en nog wat mee gestart worden. In systemd regel je dat door gebruik te maken van targets. Een target is eigenlijk niets meer dan een groep units die je gezamenlijk wilt beheren. Zo is er bijvoorbeeld de sound.target, waarmee je alle units die iets met geluid te maken hebben kunt beheren. Sommige targets kunnen ook gebruikt worden om te bepalen wat er gestart moet worden bij het starten van je systeem. Het gaat hier om de volgende targets:

  • target: de standaard target op systemen waar een grafische desktop gestart wordt. Zorgt voor het opstarten van een volledige grafische omgeving.
  • multi-user.target: de standaard target op veel server systemen. Zorgt dat alle benodigde services gestart worden, maar start geen grafische omgeving.
  • target: een target die behulpzaam kan zijn als je systeem niet meer normaal wil starten. In rescue target worden alle units gestart die ook echt nodig zijn voor een minimaal werkend systeem.
  • target: de meest minimale target. Hierin start je alleen die onderdelen die echt nodig zijn om een minimaal werkend systeem te krijgen.

Een target zorgt er dus voor dat units automatisch gestart kunnen worden. Om dit voor elkaar te krijgen, heeft elke unit een [install] sectie. In dit deel van de unit file vind je de regel WantedBy, waar je aangeeft aan welke target de unit wordt toegevoegd als je besluit hem met systemctl enable aan te zetten voor automatisch opstarten. In de eerdere listing 1 zie je hoe deze regel eruitziet.

Behalve het toevoegen van units aan targets, kan je ook kiezen welke target er gestart wordt bij het starten van je systeem. Met de opdracht systemctl get-default zie je wat er nu als standaard target staat ingesteld. Met systemctl set-default kan je zelf een andere target als standaard instellen. Dat is echter niet iets wat je heel vaak zult doen, want waarom zou je een grafische desktop ineens opstarten zonder grafische desktop?

Het opstarten van een andere target kan wel heel handig zijn bij troubleshooting. Mocht het ooit gebeuren dat je Linux systeem niet meer opstart omdat er ergens iets fout gaat, dan kan je tijdens het opstarten een andere target meegeven op de Grub boot prompt. Zorg dan dat je tijdens het opstarten de Grub prompt activeert, en vanaf de Grub prompt type je dan systemd.unit=emergency.target (zie afbeelding 1). Je systeem zal dan starten met een minimaal aantal services dat het eenvoudiger maakt om te troubleshooten. Als je root account beveiligd is met een wachtwoord, zul je dat wel eerst in moeten voeren voordat je in de troubleshooting modus terecht komt. En als je klaar bent en het probleem hebt opgelost, dan start je eenvoudig je normale target weer op met de opdracht systemctl start default.target.