I Linuxdistributioner med systemd går det att köra tjänster som vanliga användare. Med något som heter lingering går det dessutom att köra tjänster även om den aktuella användaren inte är inloggad.

Pingviner Bild: Terri Stalons

För några år sedan skrev vi om hur man hanterar tjänster med systemd. Men med systemd kan vi även skapa tjänster på användarnivå. Det innebär att varje användare på systemet kan köra sina egna tjänster.

Om användaren inte behöva köra några tjänster när hon är utloggad behöver vi inte ens ändra något på systemnivå. Det fungerar direkt. Som demonstration skapar vi ett enkelt Bash-skript som får agera som vår demon. Skriptet kommer att skriva ut aktuellt klockslag och en text till en namngiven rörleding – en FIFO.

Vi döper skriptet till demon-ex1.sh och sparar det i hemkatalogen. I mitt fall är detta /home/jake. Skriptet ser ut som nedan:

#!/bin/bash
fifofil="min-fifo-ex1"

if [ -p "${HOME}/${fifofil}" ]; then
    echo "FIFOn finns redan, använder den"
elif [ -f "${HOME}/${fifofil}" ]; then
    >&2 echo "Filen finns men är inte en FIFO, avbryter"
    exit 1;
else
    echo "Skapar en ny FIFO med namnet ${HOME}/${fifofil}"
    mkfifo ${HOME}/${fifofil}
fi

while true
do
    echo "Klockan är $(date)" > ${HOME}/${fifofil}
    sleep 1
done

Vi gör skriptet körbart innan vi går vidare:

jake~$> chmod +x demon-ex1.sh

Nu kan vi testköra skriptet. När det körs kommer det att skriva ut aktuellt datum och klockslag till den namngivna rörledningen ~/min-fifo-ex1. När vi skriver ut innehållet från filen med exempelvis cat kommer vi se meddelandet. Ett nytt meddelande kommer då också att skrivas till rörledningen och lagras där tills nästa gång vi skriver ut innehållet.

jake~$> ./demon-ex1.sh
Skapar en ny FIFO med namnet /home/jake/min-fifo-ex1

I en ny terminal kan vi nu skriva ut innehållet från rörledningen:

jake~$> cat ~/min-fifo-ex1
Klockan är fre 20 maj 2022 20:37:27 CEST

Notera att klockslaget är från när meddelandet skrevs till rörledningen, inte när vi skriver ut innehållet med cat.

Innan vi går vidare stänger vi av demonen genom att tycka Ctrl+Ci terminalen med demonen.

Skapa en användartjänst

Nu kan vi skapa en systemd-tjänst åt demonen. Vi börjar med att skapa katalogerna där vi ska placera .service-filen för tjänsten.

jake~$> mkdir -p ~/.config/systemd/user

I katalogen ~/.config/systemd/user skapar vi en ny fil som vi döper till demon-ex1.service. Innehållet i demon-ex1.service ska se ut som nedan:

[Unit]
Description=Demonexempel

[Service]
Type=simple
StandardOutput=journal
ExecStart=/home/jake/demon-ex1.sh

[Install]
WantedBy=default.target

Detta är själva tjänstefilen för demonen. Det är den som systemd använder för att starta tjänsten. Vi kan nu aktivera och starta den:

jake~$> systemctl --user enable demon-ex1
Created symlink /home/jake/.config/systemd/user/multiuser.target.wants/demon-ex1.service → /home/jake/.config/systemd/user/demon-ex1.service.

jake~$> systemctl --user start demon-ex1

Kontrollera därefter statusen för tjänsten:

jake~$> systemctl --user status demon-ex1
● demon-ex1.service - Demonexempel
     Loaded: loaded (/home/jake/.config/systemd/user/demon-ex1.service; enabled; vendor preset: enabled)
     Active: active (running) since Fri 2022-05-20 20:55:28 CEST; 7s ago
   Main PID: 1199 (demon-ex1.sh)
      Tasks: 1 (limit: 2340)
     Memory: 532.0K
        CPU: 7ms
     CGroup: /user.slice/user-1000.slice/user@1000.service/app.slice/demon-ex1.service
             └─1199 /bin/bash /home/jake/demon-ex1.sh

Allting fungerar således och tjänsten är aktiv. Nu kan vi testa att ut skriva rörledningens innehåll:

jake~$> cat ~/min-fifo-ex1
Klockan är fre 20 maj 2022 21:06:27 CEST

Vi kan också läsa journalen – loggen – för tjänsten med journalctl:

jake~$> journalctl --user -u demon-ex1
-- Journal begins at Thu 2022-01-13 18:00:14 CET, ends at Fri 2022-05-20 21:24:36 CEST. --
maj 20 20:55:28 knatte.nixnet.jke systemd[1069]: Started Demonexempel.
maj 20 20:55:28 knatte.nixnet.jke demon-ex1.sh[1199]: Skapar en ny FIFO med namnet /home/jake/min-fifo-ex1

Men om vi loggar ut användaren från alla sessioner kommer tjänsten att avslutas. Detta kan vi bekräfta genom att logga in som en annan användare och söka efter demon-ex1.sh med exempelvis pgrep.

jake~$> exit
logout

login: kalle
password:

kalle~$> pgrep demon-ex1.sh

Men om vi loggar in som användaren som skapade tjänsten kommer den att startas igen:

kalle~$> exit
logout

login: jake
password:

jake~$> pgrep demon-ex1.sh
1262546

Tillåt utloggade användare att köra tjänster

Det går dock att tillåta att tjänster fortsätter att köras även när användaren är utloggad. Det kallas för lingering. Aktiverar vi det kommer dessutom användarens tjänster att startas när datorn startas, även om användaren aldrig loggar in. Lingering aktiveras per användarbasis. Aktiveringen måste göras av root-användaren.

Som root, exekvera följande kommando. Byt ut jake mot din egna användare:

#> loginctl enable-linger jake

Vi kan se vilka användare som har lingering aktiverat genom att lista filerna i /var/lib/systemd/linger. Varje användaren med lingering aktiverat har en fil i den katalogen.

#> ls /var/lib/systemd/linger
jake

Nu kan vi logga ut från alla sessioner. Tjänsten kommer fortsätta att köras i bakgrunden. Vi kan till och med starta om datorn. När datorn startar kommer också användarens tjänster att starta.

#> reboot

Efter omstarten kan vi söka efter demon som en annan användare:

kalle~$> pgrep demon-ex1.sh
1264511

Vi har nu en fullt fungerade tjänst som körs under en vanlig användare.

Demonstration

I videon nedan demonstreras att demonen avslutas när vi loggar ut – såvida inte lingering är aktiverat för användaren.