Cos'è systemd, come funziona e come gestire i servizi Linux
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> | ||
|---|---|---|
| Tipo | Estensione | Cosa descrive |
| service | .service | un servizio: un processo demone o un'attività una tantum |
| timer | .timer | l'esecuzione di un'altra unit secondo una pianificazione (sostituisce cron) |
| socket | .socket | un socket che avvia il servizio quando arriva una connessione |
| target | .target | un gruppo di unit, cioè uno «stato del sistema» (ad esempio multi-user.target) |
| mount | .mount | un punto di mount |
| path | .path | il 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> | |
|---|---|
| Comando | Cosa fa |
systemctl status nginx | stato del servizio, PID, memoria, ultime righe del log |
systemctl start nginx | avvia adesso |
systemctl stop nginx | ferma |
systemctl restart nginx | riavvia (stop + start) |
systemctl reload nginx | rilegge la configurazione senza fermare il servizio (se supportato) |
systemctl enable nginx | abilita l'avvio automatico |
systemctl disable nginx | disabilita l'avvio automatico |
systemctl enable --now nginx | abilita l'avvio automatico e avvia subito |
systemctl is-active nginx | restituisce active/inactive — comodo negli script |
systemctl list-units --type=service | elenco dei servizi caricati |
systemctl --failed | unit in errore |
systemctl daemon-reload | rilegge 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 conRequires=. - [Service] — come eseguire il servizio.
Type=simplesignifica che il processo diExecStartè il servizio stesso e non va in background.User=esegue il servizio con un utente senza privilegi.Restart=on-failureriavvia il servizio, dopoRestartSecsecondi, se termina con un errore. - [Install] — cosa fa
enable.WantedBy=multi-user.targetsignifica «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 usaType=forkingconPIDFile=. - Variabili d'ambiente del profilo. Il servizio non legge
~/.bashrcné/etc/profile. Le variabili si impostano conEnvironment=oEnvironmentFile=.
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.
Questo argomento è trattato in modo approfondito, con pratica, nel corso «Linux: с нуля до уверенного администрирования».
- systemd: как на самом деле запускаются сервисы в современном Linux
- Журналы и мониторинг: journald, rsyslog и sysstat