Przejdź do treści

Systemd: Proces bootowania i pliki jednostek

Czym jest systemd? ⚙️

Systemd - system inicjalizacji i zarządzania usługami w systemach Linux, który zastąpił tradycyjny SysV init.

Było i jest wiele krytyki nt. używania systemd, ja jestem osobiście wielkim fanem samego systemd, lubię i używam go gdzie mogę...mamy 2025 rok a nie 2005 🥲

Omawiam tutaj sam system w kontekście Linuxa na serwerach i desktopach. Systemd nie przyda się w miejscu gdzie urzędzenie ma wykonywać określone zadanie i bez zbędnych dodatków, np. w embedeed, kontenerach (Alpine Linux), etc.

Główne różnice między systemd a SysV init:

Cecha Systemd SysV init
Uruchamianie usług Równoległe Sekwencyjne
Zależności Automatyczne zarządzanie Numeryczne poziomy uruchamiania
Format konfiguracji Pliki jednostek Skrypty powłoki
Logowanie Journald Syslog

Proces bootowania z systemd 🔄

Early Boot

Proces bootowania z systemd przebiega następująco:

  1. BIOS/UEFI - inicjalizacja sprzętu i odczytanie MBR/GPT dysku
  2. Bootloader (GRUB2) - ładowanie kernela i initramfs do pamięci RAM
  3. Kernel + initramfs - inicjalizacja podstawowych sterowników sprzętu
  4. systemd (PID 1) - uruchamiany jako pierwszy proces w systemie
  5. Montowanie systemów plików - montowanie systemów plików zgodnie z hierarchią
  6. Uruchamianie usług systemowych - inicjalizacja procesów, demonów i usług
  7. Prompt logowania użytkownika - końcowy etap procesu bootowania
flowchart TB
    BIOS["🧬 BIOS / UEFI"]
    BOOT["💾 Bootloader<br/>(GRUB2)"]
    KERNEL["🧠 Kernel<br/>+ initramfs"]
    SYSTEMD["🛠️ systemd<br/>(PID 1)"]
    MOUNT["🗂️ Mount<br/>filesystems"]
    TARGET["🎯 Reach<br/>default.target"]
    SERVICES["⚙️ Start<br/>services"]
    LOGIN["🔐 User<br/>login prompt"]

    subgraph BOOT_CHAIN [ ]
        direction TB
        BIOS -.-> BOOT ==> KERNEL --> SYSTEMD


    SYSTEMD --> MOUNT
    SYSTEMD --> TARGET
    MOUNT -.-> SERVICES
    TARGET --> SERVICES -.-> LOGIN

    end

    style BOOT_CHAIN fill:#333333,stroke:#aaa,stroke-width:1.5px,rx:12,ry:12

Systemd uruchamia się w kilku etapach:

a. sysinit.target

Podstawowe przygotowanie systemu:

  • Aktywacja i montowanie partyacji root (/) w trybie do odczytu
  • Inicjalizacja pseudo-systemów plików (/proc, /sys, /dev, /run)
  • Obsługa szyfrowanych systemów plików (cryptsetup, LUKS)
  • Odblokowanie zaszyfrowanych partycji z pliku /etc/crypttab
  • Utworzenie urządzeń mapper dla odmapowanych partycji
  • Uruchomienie udev do wykrywania sprzętu
  • Wczytanie wymaganych modułów jądra
  • Konfiguracja wirtualnego systemu plików w pamięci
  • Ustawienia hostname, loopback
  • Przygotowanie generatora dynamicznego kodu

Na tym etapie systemd montuje systemy plików w określonej kolejności: 1. /etc i /usr - montowane jako pierwsze, zawierają pliki konfiguracyjne i binaria 2. System plików root (/) jest remontowany jako read-write 3. Lokalne systemy plików z /etc/fstab


b. basic.target

  • Inicjalizacja podstawowych usług systemowych
  • Aktywacja socketów i timerów systemowych
  • Inicjalizacja logowania systemowego (journald)
  • Konfiguracja zegara systemowego
  • Aktywacja swapa
  • Przygotowanie generatorów jednostek systemd

Na tym etapie /var staje się dostępny, co pozwala na uruchomienie usług zapisujących dane


c. multi-user.target (zwykle default.target)

  • Uruchomienie standardowych usług systemowych
  • Pełna aktywacja sieci
  • Uruchomienie usług użytkownika
  • Aktywacja sshd i innych usług zdalnego dostępu
  • Uruchomienie lokalnych terminali logowania

Wszystkie systemy plików z /etc/fstab są zamontowane i dostępne


d. graphical.target (opcjonalnie)

  • Uruchomienie środowiska graficznego (X11 lub Wayland)
  • Menedżer logowania (gdm, lightdm, sddm itp.)
  • Usługi graficzne i interfejs użytkownika

Ten target jest rozszerzeniem multi-user.target i jest domyślny na systemach desktopowych


Typy plików jednostek systemd 📁

Systemd zarządza systemem poprzez pliki jednostek (unit files). Poniżej przedstawiam różne typy jednostek:

Namespace systemd

Systemd wyszukuje pliki jednostek w określonej kolejności i lokalizacjach:

  1. /etc/systemd/system/ - pliki konfiguracyjne lokalne (najwyższy priorytet)
  2. /run/systemd/system/ - pliki generowane w czasie działania
  3. /usr/lib/systemd/system/ - pliki instalowane przez pakiety

Systemd automatycznie rozpoznaje typ jednostki na podstawie rozszerzenia pliku (.service, .socket, .timer, itd.) i umieszcza je w odpowiednim namespace. Każdy namespace jest zarządzany przez dedykowany kontroler systemd.

1. Usługi (.service) ⚡

Standardowe usługi systemowe:

[Unit]
Description=Apache Web Server
After=network.target

[Service]
Type=forking
ExecStart=/usr/sbin/httpd -k start
ExecStop=/usr/sbin/httpd -k graceful-stop
ExecReload=/usr/sbin/httpd -k graceful
PrivateTmp=true

[Install]
WantedBy=multi-user.target

2. Timery (.timer) ⏰

Alternatywa dla crona:

[Unit]
Description=Backup every 6 hrs

[Timer]
OnBootSec=15min
OnUnitActiveSec=6h
AccuracySec=1min

[Install]
WantedBy=timers.target

Odpowiadająca usługa:

[Unit]
Description=Backup service

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh

3. Punkty montowania (.mount) 💾

Montowanie systemów plików:

[Unit]
Description=Mount NFS Share
After=network.target
Before=remote-fs.target

[Mount]
What=192.168.1.100:/shared
Where=/mnt/shared
Type=nfs
Options=defaults,noatime,_netdev
TimeoutSec=10

[Install]
WantedBy=multi-user.target

Systemd dla każdego wpisu w /etc/fstab automatycznie generuje odpowiedni plik .mount. Nazwa pliku jednostki musi ściśle odpowiadać ścieżce montowania, z / zamienionymi na - (np. dla /mnt/data nazwa jednostki to mnt-data.mount).

Niektóre ważne opcje sekcji [Mount]:

  • What - źródło (urządzenie, zasób sieciowy)
  • Where - punkt montowania w systemie plików
  • Type - typ systemu plików (ext4, nfs, btrfs itp.)
  • Options - opcje montowania
  • DirectoryMode - uprawnienia dla punktu montowania
  • SloppyOptions - czy ignorować nieznane opcje montowania
  • LazyUnmount - czy używać opcji lazy przy odmontowywaniu
  • ForceUnmount - czy wymuszać odmontowanie
  • ReadWriteOnly - czy montować tylko w trybie read-write

4. Sockety (.socket) 🔌

Jednostki typu socket pozwalają na aktywację usług dopiero przy pierwszym połączeniu, co oszczędza zasoby systemowe. Każdy socket jest powiązany z usługą o tej samej nazwie bazowej (np. sshd.socket z sshd.service). Systemd implementuje aktywację na żądanie (socket activation), gdzie daemon nie musi działać cały czas, tylko jest uruchamiany przez systemd, który nasłuchuje za niego.

[Unit]
Description=OpenSSH Server Socket

[Socket]
ListenStream=22
Accept=yes

[Install]
WantedBy=sockets.target

5. Ścieżki (.path) 🔍

Jednostki .path pozwalają na monitorowanie zmian w systemie plików i aktywowanie powiązanych usług, gdy wystąpi określone zdarzenie. Mogą one śledzić pojawienie się pliku, jego modyfikację lub zmianę atrybutów. Są świetną alternatywą dla inotify() i pozwalają na uruchamianie akcji bez konieczności stosowania pętli czy narzędzi monitorujących.

Notka

Nie nadaje się do monitoriowania zmian w NFS
[Unit]
Description=Check /etc/nginx path

[Path]
PathChanged=/etc/nginx/
Unit=nginx-reload.service

[Install]
WantedBy=multi-user.target

Odpowiadająca usługa:

[Unit]
Description=Reload nginx config

[Service]
Type=oneshot
ExecStart=/bin/systemctl reload nginx

6. Urządzenia (.device) 🖨️

Jednostki .device w systemd są tworzone automatycznie przez system na podstawie informacji z udev i służą do reprezentowania urządzeń sprzętowych, takich jak dyski czy interfejsy sieciowe