Perché un servizio si riavvia da solo
Quando un servizio parte correttamente ma poi si ferma e viene riavviato in automatico, il problema di solito non è “il servizio in sé”, ma il motivo per cui il sistema o il manager del servizio lo sta facendo cadere e ripartire. Le cause più comuni sono un crash dell’applicazione, un controllo di salute che fallisce, un watchdog esterno, limiti di memoria o file descriptor superati, dipendenze non disponibili oppure una configurazione che manda il processo in loop.
La differenza rispetto a un servizio che “non parte” è importante: qui il demone riesce ad avviarsi, quindi il punto giusto da osservare è cosa succede subito dopo l’avvio, non solo il comando di start.
Diagnosi probabile
Le ipotesi più frequenti, in ordine pratico, sono queste:
- Crash dell’applicazione dopo il bootstrap, spesso per errori di configurazione, connessione a database, file mancanti o variabili d’ambiente errate.
- Restart policy del service manager troppo aggressiva, che riavvia il processo appena esce con codice non zero.
- OOM killer o limiti di memoria: il kernel termina il processo e il manager lo riavvia.
- Watchdog esterno o health check che decide che il servizio è degradato e forza il restart.
- Dipendenza non pronta, per esempio database, socket, mount o rete, con effetto a catena sul processo principale.
Il primo obiettivo non è “fermare i riavvii”, ma capire se il servizio sta crashando, venendo ucciso, o se è il sistema a spingerlo in restart.
Verifiche immediate
- Controlla lo stato del servizio e il motivo dell’ultimo stop. Su sistemi con systemd, il comando più utile è:
systemctl status NOME_SERVIZIO --no-pagerEsito atteso: trovi il codice di uscita, l’ora dell’ultimo restart e spesso una riga con l’errore immediatamente precedente al riavvio.
- Leggi i log recenti del servizio:
journalctl -u NOME_SERVIZIO -n 100 --no-pagerEsito atteso: individui un errore ripetuto, come connessione negata, file non trovato, segnale di terminazione o eccezione dell’applicazione.
- Verifica se il kernel ha ucciso il processo per memoria:
journalctl -k -n 100 --no-pager | grep -iE 'oom|killed process|out of memory'Esito atteso: se compare il nome del processo, il riavvio è molto probabilmente dovuto a pressione memoria.
- Controlla i restart recenti, utile per capire se c’è un loop:
systemctl show NOME_SERVIZIO -p NRestarts,ExecMainCode,ExecMainStatus,Restart,RestartUSecEsito atteso: un numero alto di restart in poco tempo conferma il comportamento ciclico.
Soluzione consigliata passo-passo
- Isola la causa prima di toccare la policy di restart. Se il servizio è in produzione, evita di disabilitare subito il riavvio automatico: rischi di trasformare un crash loop in un down permanente. Prima identifica l’errore preciso nei log e verifica se è riproducibile manualmente.
- Se il log indica un problema di configurazione, correggi solo l’elemento segnalato. Esempi tipici: credenziali errate, path sbagliati, porta già occupata, file di certificato mancante, permessi insufficienti, variabile d’ambiente non valorizzata. Dopo la correzione, ricarica il servizio e verifica che non riparta più in loop:
systemctl restart NOME_SERVIZIOControllo successivo:
systemctl status NOME_SERVIZIO --no-pagerdeve mostrare active (running) senza restart continui. - Se sospetti un problema di dipendenze, verifica il servizio collegato prima del restart. Per esempio database, cache, storage o rete. Se il demone parte prima della dipendenza, valuta un ordine di avvio più corretto o una dipendenza esplicita nel file unit di systemd. Backup del file prima di modificarlo, ad esempio
/etc/systemd/system/NOME_SERVIZIO.service:cp /etc/systemd/system/NOME_SERVIZIO.service /etc/systemd/system/NOME_SERVIZIO.service.bakPoi aggiungi solo se necessario direttive come
After=eRequires=, quindi eseguisystemctl daemon-reloade un nuovo restart. - Se compare OOM o limiti di risorse, non aumentare subito la memoria senza verifica. Prima controlla consumo reale, log e limiti del servizio. Se serve, alza in modo conservativo i limiti di systemd nel file unit con backup preventivo, ad esempio
MemoryMaxoLimitNOFILE, solo dopo aver confermato che il processo non è semplicemente difettoso. Controllo successivo: nessun nuovo evento OOM nei log kernel e stabilità del processo per alcuni minuti. - Se il servizio è in crash loop per un bug applicativo, applica un workaround minimo e reversibile: disattiva temporaneamente il restart aggressivo solo se serve a fermare l’effetto a catena e raccogliere evidenze. Nel file unit, dopo backup, puoi passare da restart immediato a un comportamento meno aggressivo, ma solo come misura temporanea. Il fix vero resta la correzione del bug o della configurazione che causa l’uscita del processo.
Esempio pratico di lettura rapida
Se il comando systemctl status mostra un servizio che passa da active a failed in pochi secondi e il journal riporta una riga come “connection refused to database” o “cannot open file”, hai già quasi la diagnosi: il processo si avvia, prova a inizializzarsi e si chiude perché non trova una risorsa essenziale. Se invece nei log compare solo “Killed” o trovi eventi OOM nel kernel, il colpevole è la pressione memoria, non l’applicazione in senso stretto.
Un altro caso frequente è il timeout di startup: il servizio non è davvero guasto, ma impiega più tempo del previsto e il manager lo considera fallito. In quel caso il fix può essere aumentare il timeout di avvio, ma solo dopo aver verificato che il ritardo sia stabile e legittimo, non un sintomo di un problema più serio.
Controlli finali / rollback
- Verifica stabilità: dopo il fix, controlla il servizio per almeno 5-10 minuti con
systemctl status NOME_SERVIZIO --no-pagere con i log recenti. Esito atteso: nessun nuovo restart e nessun errore ripetuto. - Conferma il comportamento su rete o funzionalità applicativa: se il servizio espone una porta o una web app, prova la connessione reale e non solo lo stato interno. Il servizio deve rispondere in modo coerente con il suo ruolo.
- Rollback: se una modifica al file unit o alla configurazione peggiora la situazione, ripristina il backup creato prima dell’intervento e ricarica systemd con
systemctl daemon-reload, poi riavvia il servizio. Condizione di successo: il comportamento torna allo stato precedente all’ultima modifica.
Assunzione operativa: i comandi sopra sono pensati per un server Linux con systemd; su altri init system la logica resta la stessa, ma cambiano i comandi di stato e log.
Commenti (0)
Nessun commento ancora.
Segnala contenuto
Elimina commento
Eliminare definitivamente questo commento?
L'azione non si può annullare.