Un servizio web che rallenta, un worker ucciso senza messaggio chiaro o un server che swap non ha necessariamente esaurito tutta la RAM della macchina. Con systemd, un limite impostato su un’unità può essere sufficiente a spiegare il sintomo.
Gli cgroups consentono al kernel Linux di contare, limitare e dare priorità alle risorse di un gruppo di processi. Prima di aggiungere memoria o riavviare a caso, verifica cosa applica systemd al servizio interessato.

Vedi il cgroup di un servizio
Su distribuzioni recenti, systemd colloca ogni servizio nel proprio cgroup. Non devi spostare i PID a mano per diagnosticare un’unità classica come Nginx, PostgreSQL o un worker applicativo.
Inizia leggendo lo stato del servizio e le proprietà legate alle risorse. Sostituisci nginx.service con il nome reale della tua unità.
systemctl status nginx.service --no-pager
systemctl show nginx.service -p ControlGroup -p MainPID -p MemoryCurrent -p MemoryMax -p MemoryHigh -p CPUQuotaPerSecUSec
ControlGroup fornisce il percorso gestito da systemd. MemoryCurrent visualizza la memoria conteggiata per l’unità al momento della lettura. Se MemoryMax vale infinity, systemd non ha impostato un limite di memoria rigoroso su questo servizio.
Se stai partendo da un PID, rileggi il suo cgroup da /proc. In cgroup v2, vedrai spesso una riga del tipo 0::/system.slice/nginx.service.
pid=$(systemctl show nginx.service -p MainPID --value)
cat /proc/$pid/cgroup
Se MainPID vale 0, il servizio non ha un processo principale attivo. Torna a systemctl status e a journalctl invece di concludere a partire da un PID vuoto.
Leggi i limiti di memoria e CPU
MemoryMax è un limite rigoroso. Se il cgroup raggiunge questo tetto e il kernel non recupera abbastanza memoria, un processo del gruppo può essere ucciso dall’OOM killer.
MemoryHigh è meno brusco. Il kernel frena le allocazioni e cerca di recuperare memoria quando il cgroup supera questa soglia. Per contenere un servizio senza farlo cadere al primo picco, è spesso una migliore prima impostazione rispetto a MemoryMax.
CPUQuota limita il tempo CPU disponibile per il servizio. CPUQuota=25% fornisce l’equivalente di un quarto di core logico. Su una macchina con più core, CPUQuota=200% consente fino a due core di tempo CPU.
systemctl show nginx.service
-p MemoryCurrent -p MemoryMax -p MemoryHigh
-p CPUUsageNSec -p CPUQuotaPerSecUSec
Non mescolare quota e priorità. Una quota impedisce al servizio di superare una certa quantità di CPU. Una priorità, con nice o CPUWeight, arbitra soprattutto la concorrenza quando più attività richiedono CPU allo stesso tempo.
Trovare l’origine di un limite
Un limite può provenire dal file fornito dal pacchetto, da un drop-in systemd o da un override creato localmente. Leggi la configurazione completa prima di modificare il servizio.
systemctl cat nginx.service
systemctl show nginx.service -p FragmentPath -p DropInPaths
Un file sotto /etc/systemd/system/nginx.service.d/ di solito ha la precedenza sull’unità fornita dal pacchetto. Evita di modificare direttamente un file in /usr/lib/systemd/system/ o /lib/systemd/system/, poiché un aggiornamento potrebbe sovrascriverlo.
Controlla quindi i sintomi. Un servizio rallentato potrebbe derivare anche da una query SQL lenta, da un disco saturato, da una coda piena o da un errore applicativo.
journalctl -u nginx.service -b --no-pager
journalctl -k -b | grep -Ei 'oom|out of memory|killed process|memory cgroup'
Se i limiti restano a infinity e il journal del kernel non mostra alcun evento di memoria, cerca altrove prima di toccare i cgroups: registri applicativi, metriche disco, latenza rete o consumo reale del processo.
Testare senza toccare il servizio
Per convalidare una sintassi o misurare l’effetto di un limite, avvia un’unità temporanea con systemd-run. Il test non modifica Nginx, PostgreSQL o il tuo servizio principale.
sudo systemd-run --unit=prova-limite-memoria
--property=MemoryMax=256M
--property=CPUQuota=25%
/usr/bin/bash -c 'sleep 300'
Leggi poi le proprietà applicate. Per CPUQuota=25%, systemd può visualizzare un valore equivalente a 250ms al secondo.
systemctl show prova-limite-memoria.service
-p MemoryMax -p CPUQuotaPerSecUSec -p ControlGroup -p ActiveState
systemctl cat prova-limite-memoria.service
Ferma l’unità di test non appena hai finito. Con sleep, dimenticarsi è senza gravità, ma questo riflesso evita sorprese quando il test esegue un vero comando.
sudo systemctl stop prova-limite-memoria.service
Applicare un override systemd
Quando i registri e le misurazioni confermano che un limite ha senso, passa a un override systemd. L’esempio seguente imposta una soglia alta a 800 MB, un tetto rigoroso a 1 GB e limita il servizio all’equivalente di un core CPU.
sudo systemctl edit mio-servizio.service
Aggiungi solo le direttive necessarie. Non copiare questi valori su un servizio di produzione senza aver osservato il suo consumo normale e i suoi picchi.
[Service]
MemoryHigh=800M
MemoryMax=1G
CPUQuota=100%
Ricarica systemd, quindi riavvia il servizio solo se l’interruzione è accettabile. Da remoto, mantieni aperta una seconda sessione SSH quando tocchi un componente critico.
sudo systemctl daemon-reload
sudo systemctl restart mio-servizio.service
systemctl status mio-servizio.service --no-pager
systemctl show mio-servizio.service -p MemoryCurrent -p MemoryHigh -p MemoryMax -p CPUQuotaPerSecUSec
Se il servizio non parte più o diventa troppo lento, rimuovi l’override con cautela. sudo systemctl revert mio-servizio.service rimuove gli override locali dell’unità. Non usarlo se la stessa directory contiene altre impostazioni da mantenere.
Controlli dopo il cambiamento
- Controlla lo stato con
systemctl is-active mio-servizio.service. - Rileggi
MemoryCurrent,MemoryHigh,MemoryMaxeCPUQuotaPerSecUSecdopo il riavvio. - Monitora
journalctl -u mio-servizio.service -be il journal del kernel durante il picco di carico che dava problemi. - Misura l’effetto a livello di applicazione: tempo di risposta, lavori in ritardo, code, errori utente.
- Annota il motivo della regolazione, la data, il valore adottato e il sintomo corretto nella tua procedura operativa.
I cgroups proteggono il resto della macchina e rendono i limiti visibili. Non correggono una perdita di memoria, una query troppo costosa o un worker mal dimensionato. Se il tetto viene raggiunto, conserva il registro, il carico osservato e il valore configurato per decidere se regolare il limite o correggere l’applicazione.
Per approfondire, la pagina systemd.resource-control(5) dettaglia ogni direttiva. La guida Nice su Linux aiuta a scegliere una priorità CPU quando un limite rigoroso non è adatto.