Un server web, un database, il servizio SSH, la rete: sono tutti servizi che girano in background. Con systemctl si controlla se funzionano, si avviano, si fermano, si riavviano e si decide se devono partire all'accensione del computer. È il comando che userai più spesso quando gestisci un server.
Cos'è
systemctl è lo strumento di controllo di systemd, il sistema che avvia il computer e gestisce i servizi in quasi tutte le distribuzioni moderne (Debian, Ubuntu, Fedora, Arch e molte altre). Il lavoro è organizzato in unità (unit), ciascuna descritta da un file di configurazione. Le più comuni sono i servizi (nginx.service) e i timer (backup.timer); esistono anche .socket, .mount e .target (gruppi di unità, come multi-user.target). Per i servizi l'estensione .service si può omettere: systemctl status nginx equivale a nginx.service.
Cosa fa
Mostra lo stato delle unità e le gestisce: le avvia e ferma subito, le abilita o disabilita all'avvio del sistema, chiede loro di rileggere la configurazione, elenca quelle attive o in errore. Quasi tutte le operazioni che modificano qualcosa richiedono i privilegi di amministratore, quindi si usa sudo; quelle che mostrano soltanto lo stato no.
Come si usa
$ systemctl [opzioni] comando [unità]Gli esempi usano servizi comuni su Debian e Ubuntu (nginx, ssh, cron); i nomi dipendono da ciò che hai installato (per esempio, il servizio SSH è ssh su Debian e Ubuntu e sshd su Fedora, il database può chiamarsi mariadb o mysql).
Esempio 1: lo stato di un servizio
$ systemctl status nginx
● nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: enabled)
Active: active (running) since Mon 2026-10-19 08:12:41 CEST; 2 days ago
Docs: man:nginx(8)
Process: 912 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
Main PID: 925 (nginx)
Tasks: 3 (limit: 4558)
Memory: 8.2M
CPU: 1.204s
CGroup: /system.slice/nginx.service
├─925 "nginx: master process /usr/sbin/nginx -g daemon on; master_process on;"
└─927 "nginx: worker process"
ott 21 04:57:01 server nginx[925]: ...È il comando più utile. Le righe da leggere sono: Loaded (il file di configurazione e se parte all'avvio: enabled o disabled), Active (lo stato: active (running) funziona; inactive (dead) è fermo; failed è terminato con un errore) e in fondo le ultime righe di registro del servizio, spesso sufficienti a capire cosa non va. Si esce con q.
Esempio 2: avviare, fermare, riavviare
$ sudo systemctl start nginx
$ sudo systemctl stop nginx
$ sudo systemctl restart nginx
$ sudo systemctl reload nginxI comandi non stampano nulla se tutto va bene. restart ferma e riavvia il servizio (con una breve interruzione); reload gli chiede di rileggere la configurazione senza fermarsi, se il programma lo supporta (nginx, apache, sshd e molti altri): è preferibile in produzione perché non interrompe le connessioni attive. Esiste anche try-restart e reload-or-restart, che fa il reload se possibile e altrimenti il restart.
Esempio 3: avviare all'accensione con enable
$ sudo systemctl enable nginx
Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /usr/lib/systemd/system/nginx.service.
$ sudo systemctl disable nginx
Removed "/etc/systemd/system/multi-user.target.wants/nginx.service".
$ sudo systemctl enable --now nginx
$ sudo systemctl disable --now nginxstart e enable sono cose diverse. start avvia il servizio adesso, ma non dice nulla sul prossimo avvio del computer. enable lo fa partire a ogni accensione, ma non lo avvia adesso (crea un collegamento simbolico, come si vede nel messaggio). Con --now si fanno le due cose insieme: enable --now abilita e avvia, disable --now disabilita e ferma.
Esempio 4: sapere se un servizio è attivo (nel terminale e negli script)
$ systemctl is-active nginx
active
$ systemctl is-enabled nginx
enabled
$ systemctl is-failed nginx
active
$ systemctl is-active --quiet nginx && echo "nginx è in funzione"
nginx è in funzioneI comandi is-active, is-enabled e is-failed stampano una sola parola (active, inactive, failed, enabled, disabled…) e hanno un codice di uscita pensato per gli script: 0 se la condizione è vera. Con --quiet non stampano nulla.
Esempio 5: elencare i servizi
$ systemctl list-units --type=service
UNIT LOAD ACTIVE SUB DESCRIPTION
cron.service loaded active running Regular background program processing daemon
nginx.service loaded active running A high performance web server
ssh.service loaded active running OpenBSD Secure Shell server
...
$ systemctl list-units --type=service --state=running
$ systemctl list-unit-files --type=service | grep enabled
$ systemctl --failed
UNIT LOAD ACTIVE SUB DESCRIPTION
● mariadb.service loaded failed failed MariaDB database serverlist-units mostra le unità attualmente in memoria; con --type=service solo i servizi e con --state=running solo quelli in esecuzione. list-unit-files elenca tutti i file installati con il loro stato di abilitazione. systemctl --failed mostra solo ciò che è in errore, ed è un buon primo controllo dopo l'avvio di un server. Il pallino ● segnala un'unità con un problema.
Esempio 6: leggere i registri con journalctl
$ journalctl -u nginx
$ journalctl -u nginx -n 50 --no-pager
$ journalctl -u nginx -f
$ journalctl -u nginx --since "1 hour ago"
$ journalctl -p err -bI messaggi dei servizi finiscono nel journal di systemd, che si legge con journalctl, il compagno inseparabile di systemctl. Con -u unità si filtra per servizio, -n 50 mostra le ultime 50 righe, -f segue i messaggi man mano che arrivano (come tail -f; si esce con Ctrl+C), --since limita nel tempo e -p err -b mostra gli errori dall'ultimo avvio. Con --no-pager l'output non passa per less, utile se lo si invia a un altro comando.
Esempio 7: dopo una modifica alla configurazione
$ sudo nano /etc/nginx/sites-available/miosito
$ sudo nginx -t
nginx: configuration file /etc/nginx/nginx.conf test is successful
$ sudo systemctl reload nginx
$ systemctl status nginx --no-pager | head -n 4Un flusso di lavoro tipico: si modifica il file, si verifica la sintassi con lo strumento del programma (qui nginx -t) e solo dopo si applica la modifica con reload. Così un errore di battitura non butta giù il sito. Infine si controlla lo stato.
Esempio 8: un servizio che non parte
$ sudo systemctl start mariadb
Job for mariadb.service failed because the control process exited with error code.
See "systemctl status mariadb.service" and "journalctl -xeu mariadb.service" for details.
$ systemctl status mariadb --no-pager
× mariadb.service - MariaDB 10.11.6 database server
Active: failed (Result: exit-code) since ...
$ journalctl -xeu mariadb.service --no-pager | tail -n 20Quando un servizio non parte, il messaggio d'errore indica già i due comandi da usare: systemctl status per lo stato e le ultime righe, journalctl -xeu unità per i dettagli (-x aggiunge spiegazioni, -e salta alla fine, -u filtra per unità). Il motivo più frequente è nelle ultime righe: file mancante, porta già occupata, errore di configurazione, permessi sbagliati.
Esempio 9: leggere o modificare un'unità
$ systemctl cat nginx
# /usr/lib/systemd/system/nginx.service
[Unit]
Description=A high performance web server and a reverse proxy server
After=network.target
[Service]
ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;'
...
$ sudo systemctl edit nginx
$ sudo systemctl daemon-reloadsystemctl cat mostra il file dell'unità. Non conviene modificare i file in /usr/lib/systemd/system/, perché un aggiornamento del pacchetto li sovrascrive: sudo systemctl edit nome apre un editor per creare un file di modifiche (un drop-in, salvato in /etc/systemd/system/nome.service.d/override.conf) che si applica sopra l'originale. Dopo aver modificato a mano un file di unità si esegue sudo systemctl daemon-reload, per fare rileggere a systemd tutti i file; systemctl edit lo fa automaticamente. Per applicare le modifiche al servizio serve poi un restart.
Esempio 10: creare un proprio servizio
$ sudo nano /etc/systemd/system/mio-script.service
[Unit]
Description=Il mio script
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=enzo
WorkingDirectory=/home/enzo/progetto
ExecStart=/usr/bin/python3 /home/enzo/progetto/app.py
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
$ sudo systemctl daemon-reload
$ sudo systemctl enable --now mio-script
$ systemctl status mio-script --no-pagerPer far girare un proprio programma come servizio basta un piccolo file in /etc/systemd/system/. Le sezioni sono tre: [Unit] (descrizione e ordine di avvio), [Service] (utente, cartella, comando da eseguire con percorsi assoluti, riavvio automatico con Restart=on-failure) e [Install] (in quale target inserirlo quando lo si abilita). Dopo daemon-reload, enable --now lo attiva subito e a ogni avvio. Rispetto a cron e a nohup, systemd tiene il programma sotto controllo, lo riavvia se cade e ne conserva i registri.
Esempio 11: i timer, l'alternativa moderna a cron
$ systemctl list-timers
NEXT LEFT LAST PASSED UNIT ACTIVATES
Thu 2026-10-22 00:00:00 CEST 19h left Wed 2026-10-21 00:00:01 CEST 4h ago dpkg-db-backup.timer dpkg-db-backup.service
Thu 2026-10-22 06:12:33 CEST 1h 15min left Wed 2026-10-21 06:09:11 CEST ... apt-daily-upgrade.timer apt-daily-upgrade.serviceUn timer è un'unità che avvia un servizio a una certa ora o a intervalli. Rispetto a cron recupera i lavori saltati a computer spento (con Persistent=true) e salva i registri nel journal. list-timers mostra quelli attivi con il prossimo e l'ultimo avvio. Nella tabella di cron si scrive una riga; con un timer servono due file (.service e .timer), ma si ottiene più controllo.
Esempio 12: riavviare o spegnere il computer, e il livello di avvio
$ sudo systemctl reboot
$ sudo systemctl poweroff
$ systemctl get-default
graphical.target
$ sudo systemctl set-default multi-user.targetreboot e poweroff riavviano e spengono il computer. get-default mostra in quale modalità il sistema si avvia: graphical.target con ambiente grafico, multi-user.target solo testuale (la scelta tipica di un server). Questo comando è sensibile: cambiarlo su un computer da scrivania significa ritrovarsi senza desktop al prossimo avvio.
Esempio 13: mascherare, e controllare i servizi dell'utente
$ sudo systemctl mask apache2
Created symlink /etc/systemd/system/apache2.service → /dev/null.
$ sudo systemctl unmask apache2
$ systemctl --user status pipewire
$ systemctl --user list-units --type=serviceCon mask un servizio viene reso impossibile da avviare, anche manualmente o come dipendenza di altri servizi (diverso da disable, che toglie solo l'avvio automatico); si annulla con unmask. Con --user si gestiscono i servizi dell'utente corrente, senza sudo: sono quelli della sessione, come l'audio con PipeWire.
Opzioni utili
status: stato e ultime righe di registro;is-active,is-enabled,is-failed: una sola parola, adatte agli script.start/stop/restart/reload/reload-or-restart: gestione immediata.enable/disable: partenza all'avvio del sistema;--now: fa anche l'operazione immediata.mask/unmask: blocca completamente un'unità / annulla.list-units,list-unit-files,list-timers,--failed: elenchi.--type=service,--state=running,-a: filtri perlist-units.cat/edit/daemon-reload: leggere, modificare e ricaricare i file delle unità.show nome -p Proprietà: valori delle proprietà di un'unità, adatti agli script.--user: servizi dell'utente corrente;--no-pager: nienteless.reboot,poweroff,get-default,set-default: riavvio, spegnimento e modalità di avvio.
Attenzione a
startnon èenable: un servizio avviato a mano non ripartirà al prossimo avvio, e uno abilitato non è per forza in funzione adesso. Per entrambe le cose,enable --now.reloadorestart?restartinterrompe il servizio, anche se per poco;reloadrilegge la configurazione senza fermarlo, ma non tutti i servizi lo supportano (in tal caso dà errore). Dopo unreloadcontrolla comunque lo stato.- Verifica la configurazione prima di applicarla: strumenti come
nginx -toapachectl configtestevitano di fermare un sito per un errore di battitura. Fermare un servizio con una configurazione sbagliata e provare a riavviarlo è il modo più rapido di restare senza sito. - Non fermare ciò da cui dipendi: fermare
sshmentre sei collegato via SSH può chiuderti fuori (la sessione già aperta in genere resta, ma una nuova connessione può non essere più possibile, a seconda di come è configurato il servizio). Lo stesso vale per i servizi di rete. Su un server remoto, prima distop,restartodisabledi servizi comessho la rete, tieni aperta una seconda sessione di riserva. - Dopo aver modificato un file di unità,
daemon-reload: senza, systemd usa ancora la vecchia versione e avvisa con "The unit file changed on disk". - Non modificare i file in
/usr/lib/systemd/system/: gli aggiornamenti li sovrascrivono. Usasystemctl edito i file in/etc/systemd/system/. - Percorsi assoluti nelle unità: in
ExecStartil programma va indicato con il percorso completo (/usr/bin/python3), e l'ambiente del servizio è minimo, come incron. Reindirizzamenti, pipe e variabili della shell non funzionano direttamente: per usarli si lancia/bin/bash -c '...'. - Servizi che si riavviano all'infinito: con
Restart=alwaysun programma che si chiude subito viene rilanciato di continuo (systemd si ferma dopo troppi tentativi ravvicinati, con lo statofailed, ma consumando risorse). Controlla sempre il registro. - Modalità di arresto brusche:
systemctl powerofferebootspengono subito il computer; su un server remoto verifica di essere sul computer giusto prima di digitarli. - I nomi dei servizi variano:
sshosshd,apache2ohttpd,mysqlomariadb. Consystemctl list-unit-files | grep nomeo la funzione di completamento con Tab trovi quello giusto. - Non tutto usa systemd: alcune distribuzioni (Alpine, Void, Devuan, Gentoo con OpenRC) e i container Docker normalmente non lo usano: in quel caso
systemctlnon funziona e servono altri strumenti (rc-service,sv,service). Dentro un container si usa il comando del contenitore (docker restart,docker compose), nonsystemctl. - I servizi non sono processi qualsiasi: un programma avviato a mano (per esempio
nginxdal terminale) non è conosciuto da systemd, che mostrerà il servizio come fermo anche se il programma è in esecuzione. Se vuoi che systemd lo gestisca, avvialo solo consystemctl. - Il vecchio comando
service:sudo service nginx restartfunziona ancora (chiamasystemctl) ed è molto diffuso in guide e tutorial; la sintassi è semplicementeservice nome comando, con l'ordine diverso.
Riepilogo
| Comando | Cosa fa |
|---|---|
systemctl status nome | Stato del servizio e ultime righe di registro |
sudo systemctl start nome | Avvia ora |
sudo systemctl stop nome | Ferma ora |
sudo systemctl restart nome | Ferma e riavvia |
sudo systemctl reload nome | Rilegge la configurazione senza fermarsi |
sudo systemctl enable --now nome | Abilita all'avvio e avvia subito |
sudo systemctl disable --now nome | Disabilita e ferma |
systemctl is-active nome | Stampa active / inactive / failed |
systemctl --failed | Elenca le unità in errore |
systemctl list-units --type=service | Elenca i servizi caricati |
systemctl list-timers | Elenca i timer |
journalctl -u nome -f | Segue i registri del servizio |
journalctl -xeu nome | Registri con dettagli per capire un errore |
systemctl cat nome / sudo systemctl edit nome | Legge / modifica la configurazione di un'unità |
sudo systemctl daemon-reload | Rilegge i file delle unità |
sudo systemctl mask nome | Impedisce del tutto l'avvio |
systemctl --user ... | Gestisce i servizi dell'utente corrente |