Basi

Cos'è systemd, come funziona e come gestire i servizi Linux

Aggiornato: · Skillaria.Top

systemd è il sistema di init e il gestore dei servizi di Linux: il kernel lo avvia come primo processo (PID 1), che avvia gli altri servizi nell'ordine giusto e li sorveglia. Tutto ciò che fa systemd è descritto dalle unit, cioè descrizioni testuali di servizi, timer e punti di mount; con systemctl le si avvia, ferma e abilita all'avvio, mentre journalctl mostra i loro log.

systemd è un sistema di init e un gestore dei servizi usato nella maggior parte delle distribuzioni Linux moderne: Debian, Ubuntu, Fedora, RHEL e derivate. Dopo l'avvio il kernel esegue systemd come primo processo con PID 1, e da lì si avviano la rete, si montano i dischi, partono il server web, il database e tutto il resto. In parole semplici, systemd è il «gestore» che sa quali servizi devono girare, in quale ordine partire e cosa fare quando un servizio si blocca.

Per verificare di avere systemd basta un comando:

$ ps -p 1 -o comm=
systemd

Perché è nato systemd

In passato Linux usava SysV init: una serie di script di shell in /etc/init.d/ eseguiti uno dopo l'altro. Era un sistema comprensibile, ma lento e fragile. Ogni script doveva scrivere il proprio file PID, decidere da sé se il processo era vivo e aggiungere a parte un meccanismo per riavviare un servizio caduto.

systemd risolve questi problemi in modo centralizzato:

  • Avvio in parallelo. I servizi che non dipendono l'uno dall'altro partono contemporaneamente, quindi il boot è più rapido.
  • Dipendenze e ordine. La definizione del servizio dichiara di cosa ha bisogno (per esempio la rete) e dopo cosa va avviato.
  • Sorveglianza. Tramite i cgroups systemd conosce tutti i processi del servizio e può riavviarlo in caso di crash.
  • Un solo log. Journald raccoglie l'output di tutti i servizi, e i log si leggono con un unico comando.
  • Un'interfaccia uniforme. Ogni servizio si gestisce allo stesso modo: systemctl start|stop|restart|status.

Oltre al gestore dei servizi, il progetto systemd comprende altri componenti: journald (log), logind (sessioni utente), timesyncd (sincronizzazione dell'ora), resolved (DNS), networkd (rete). Non tutte le distribuzioni li usano tutti, ma systemd come PID 1 e journald si trovano quasi ovunque.

Le unit: di cosa è fatto systemd

Tutto ciò che systemd gestisce è descritto da unit. Un'unit è un file di testo in formato INI, e il tipo si riconosce dall'estensione.

ead>
TipoEstensioneCosa descrive
service.serviceun servizio: un processo demone o un'attività una tantum
timer.timerl'esecuzione di un'altra unit secondo una pianificazione (sostituisce cron)
socket.socketun socket che avvia il servizio quando arriva una connessione
target.targetun gruppo di unit, cioè uno «stato del sistema» (ad esempio multi-user.target)
mount.mountun punto di mount
path.pathil monitoraggio di un file o di una directory

Dove si trovano i file unit

I file unit si trovano in più directory, con una precedenza precisa:

  • /usr/lib/systemd/system/ (in Debian e Ubuntu anche /lib/systemd/system/) — unit installate dai pacchetti. Non modificarle a mano: all'aggiornamento del pacchetto le modifiche verrebbero sovrascritte.
  • /etc/systemd/system/ — unit e override dell'amministratore. Hanno la precedenza più alta.
  • /run/systemd/system/ — unit temporanee create durante l'esecuzione.

Per vedere il contenuto finale di un'unit con tutti gli override usa systemctl cat nginx.service.

Target al posto dei runlevel

I vecchi runlevel sono stati sostituiti dai target. multi-user.target è la modalità server normale senza grafica, graphical.target quella con interfaccia grafica, rescue.target la modalità di ripristino a utente singolo. Il target predefinito si mostra con systemctl get-default e si cambia con systemctl set-default multi-user.target.

systemctl: gestire i servizi

systemctl è lo strumento principale di systemd. La maggior parte dei comandi modifica lo stato del sistema e richiede sudo.

ead>
ComandoCosa fa
systemctl status nginxstato del servizio, PID, memoria, ultime righe del log
systemctl start nginxavvia adesso
systemctl stop nginxferma
systemctl restart nginxriavvia (stop + start)
systemctl reload nginxrilegge la configurazione senza fermare il servizio (se supportato)
systemctl enable nginxabilita l'avvio automatico
systemctl disable nginxdisabilita l'avvio automatico
systemctl enable --now nginxabilita l'avvio automatico e avvia subito
systemctl is-active nginxrestituisce active/inactive — comodo negli script
systemctl list-units --type=serviceelenco dei servizi caricati
systemctl --failedunit in errore
systemctl daemon-reloadrilegge i file unit dopo una modifica

Come leggere systemctl status

$ systemctl status nginx
● nginx.service - A high performance web server and a reverse proxy server
     Loaded: loaded (/lib/systemd/system/nginx.service; enabled; preset: enabled)
     Active: active (running) since Mon 2026-10-12 09:14:03 UTC; 2h 5min ago
       Docs: man:nginx(8)
   Main PID: 812 (nginx)
      Tasks: 3 (limit: 2307)
     Memory: 6.1M
        CPU: 154ms
     CGroup: /system.slice/nginx.service
             ├─812 "nginx: master process /usr/sbin/nginx -g daemon on; master_process on;"
             ├─813 "nginx: worker process"
             └─814 "nginx: worker process"

La riga Loaded indica da dove è stato letto il file unit e se l'avvio automatico è attivo (enabled). La riga Active mostra lo stato attuale: active (running), inactive (dead) oppure failed. Il blocco CGroup elenca tutti i processi del servizio: è così che systemd sa quali processi appartengono a quale servizio.

Differenza tra enable e start

È una confusione frequente. start avvia il servizio adesso, ma dopo un riavvio non ripartirà da solo. enable crea un collegamento simbolico nella directory del target (ad esempio /etc/systemd/system/multi-user.target.wants/): all'avvio del sistema il servizio viene lanciato, ma non viene eseguito subito. Per averli entrambi usa enable --now.

Esiste anche lo stato mask. systemctl mask servizio collega l'unit a /dev/null: non può più essere avviata né a mano né come dipendenza. Serve quando un servizio deve restare sicuramente spento.

journalctl: i log dei servizi

Tutto ciò che un servizio scrive su stdout e stderr viene intercettato da systemd-journald, che lo salva in un journal binario insieme al nome dell'unit, al PID, alla priorità e all'orario. Il journal si legge con journalctl.

journalctl -u nginx              # log di un solo servizio
journalctl -u nginx -f           # segue in tempo reale, come tail -f
journalctl -u nginx --since "1 hour ago"
journalctl -u nginx -n 50        # ultime 50 righe
journalctl -b                    # dall'avvio corrente
journalctl -b -1                 # avvio precedente
journalctl -p err -b             # solo errori e livelli più gravi
journalctl -k                    # messaggi del kernel
journalctl --disk-usage          # spazio occupato dal journal

L'opzione -p filtra per priorità syslog: emerg, alert, crit, err, warning, notice, info, debug. Il livello indicato include anche tutto ciò che è più grave.

Il journal dopo il riavvio

Se la directory /var/log/journal non esiste e in /etc/systemd/journald.conf c'è Storage=auto, il journal resta solo in memoria (/run/log/journal) e si perde al riavvio. Per renderlo permanente imposta Storage=persistent oppure crea la directory e riavvia journald. La dimensione massima si regola con SystemMaxUse=, e i dati vecchi si eliminano con journalctl --vacuum-time=2weeks o --vacuum-size=500M.

journald lavora spesso insieme a rsyslog: il journal passa i messaggi a rsyslog, che scrive i classici file di testo in /var/log/ e può inviare i log a un server centrale.

Avviare automaticamente un proprio servizio: esempio di file unit

Supponiamo di avere un'applicazione, uno script o un binario, che deve restare in esecuzione, partire all'avvio del sistema e riavviarsi se si blocca. Crea il file /etc/systemd/system/myapp.service:

[Unit]
Description=My web application
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=myapp
Group=myapp
WorkingDirectory=/opt/myapp
EnvironmentFile=/etc/myapp/env
ExecStart=/opt/myapp/bin/server --port 8080
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

Vediamo le sezioni:

  • [Unit] — descrizione e dipendenze. After= stabilisce solo l'ordine, Wants= è una dipendenza debole (tira dentro l'unit, ma non fallisce se questa non parte). La dipendenza forte si scrive con Requires=.
  • [Service] — come eseguire il servizio. Type=simple significa che il processo di ExecStart è il servizio stesso e non va in background. User= esegue il servizio con un utente senza privilegi. Restart=on-failure riavvia il servizio, dopo RestartSec secondi, se termina con un errore.
  • [Install] — cosa fa enable. WantedBy=multi-user.target significa «avvia durante il normale avvio del sistema».

Per applicarlo:

sudo useradd --system --no-create-home --shell /usr/sbin/nologin myapp
sudo systemctl daemon-reload
sudo systemctl enable --now myapp
systemctl status myapp
journalctl -u myapp -f

Errori frequenti nei file unit

  • Percorso relativo in ExecStart. Il percorso del programma deve essere assoluto. systemd non cerca i comandi nel PATH dell'utente come fa la shell.
  • Dimenticare daemon-reload. Dopo una modifica al file systemd continua a usare la versione precedente e lo segnala in status.
  • Il demone va in background. Se il programma si duplica da solo (fork) ma è indicato Type=simple, systemd pensa che il servizio sia terminato. Fai girare il programma in primo piano oppure usa Type=forking con PIDFile=.
  • Variabili d'ambiente del profilo. Il servizio non legge ~/.bashrc né /etc/profile. Le variabili si impostano con Environment= o EnvironmentFile=.

Modificare un'unit di pacchetto senza toccarla

Per cambiare i parametri di un servizio installato da un pacchetto, senza modificarne il file, si usa un drop-in:

sudo systemctl edit nginx

Si apre un editor e le modifiche vengono salvate in /etc/systemd/system/nginx.service.d/override.conf. Ad esempio vi si può aggiungere Restart=always sotto [Service]. Chiudendo l'editor, systemd rilegge automaticamente la configurazione.

Timer di systemd al posto di cron

Un timer è un'unit che avvia il servizio con lo stesso nome secondo una pianificazione. Rispetto a cron: i log dell'attività finiscono nel journal, si possono definire dipendenze e le esecuzioni perse si possono recuperare (Persistent=true). Esempio di backup quotidiano:

# /etc/systemd/system/backup.service
[Unit]
Description=Nightly backup

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

# /etc/systemd/system/backup.timer
[Unit]
Description=Run backup daily

[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true

[Install]
WantedBy=timers.target
sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer
systemctl list-timers

Per verificare l'espressione OnCalendar usa systemd-analyze calendar "*-*-* 03:00:00": mostra quando avverrà la prossima esecuzione.

Diagnostica dell'avvio

systemd registra l'orario di avvio di ogni unit, quindi è facile analizzare un avvio lento:

systemd-analyze                  # tempo totale di avvio
systemd-analyze blame            # unit ordinate per tempo di avvio
systemd-analyze critical-chain   # la catena che ha ritardato l'avvio
systemd-analyze verify /etc/systemd/system/myapp.service   # controllo del file unit

Conclusioni

systemd è il PID 1 e il gestore dei servizi del Linux moderno. Descrive tutto con le unit, si controlla con systemctl, raccoglie i log in un journal letto da journalctl e, al posto di cron, può eseguire attività con i timer. Per usarlo con sicurezza bastano status, enable --now, journalctl -u e la capacità di scrivere un semplice file unit con Restart=on-failure. systemd, journald e il logging sono trattati nel corso con esercizi pratici.

Domande frequenti

Come faccio a sapere se il mio sistema usa systemd?

Esegui <code>ps -p 1 -o comm=</code>. Se l'output è systemd, il sistema funziona con systemd. Anche la directory <code>/run/systemd/system</code> esiste solo quando si avvia con systemd.

Qual è la differenza tra systemctl restart e reload?

restart ferma completamente il servizio e lo riavvia, quindi le connessioni attive si interrompono. reload chiede al servizio di rileggere la configurazione senza fermarsi, ma funziona solo se l'unit definisce <code>ExecReload</code>.

Posso eseguire servizi systemd senza sudo, come utente normale?

Sì, systemd ha un'istanza per utente: metti le unit in <code>~/.config/systemd/user/</code> e gestiscile con <code>systemctl --user</code>. Per farle girare anche senza una sessione attiva serve <code>loginctl enable-linger</code>.

Un servizio è in stato failed: perché e come si resetta?

Cerca la causa con <code>journalctl -u nome -b</code> e nella riga Active di <code>status</code>. Dopo la correzione riavvia il servizio; l'indicazione failed si cancella con <code>systemctl reset-failed</code>.

Dove sono salvati i log di systemd sul disco?

Con la memorizzazione permanente in <code>/var/log/journal/</code>, in formato binario; altrimenti in <code>/run/log/journal/</code>, in memoria. Vanno letti con <code>journalctl</code>, non con gli strumenti di testo.

Impara l’argomento in video

Questo argomento è trattato in modo approfondito, con pratica, nel corso «Linux: с нуля до уверенного администрирования».

Vai al corso