Risoluzione dei problemi dei servizi Linux con systemctl e journalctl
Un flusso di lavoro pratico per il debug di servizi Linux falliti o non funzionanti con systemctl e journalctl.
Risoluzione dei problemi dei servizi Linux con systemctl e journalctl
Quando un servizio Linux fallisce, il percorso più veloce di solito non è una ricerca sul web. Sono tre controlli locali: cosa pensa systemd che sia successo, cosa ha registrato il servizio e cosa è cambiato prima del fallimento. systemctl e journalctl ti danno queste risposte senza dover indovinare.
Questa guida utilizza come esempi fallimenti comuni dei servizi: un servizio che non si avvia, un processo che è in esecuzione ma non svolge lavoro utile e un servizio che termina dopo essere sembrato sano. I comandi si applicano alla maggior parte dei servizi gestiti da systemd, ma i nomi esatti delle unità e le posizioni dei log variano in base alla distribuzione e al pacchetto.
Comprendere systemctl e journalctl
Prima di addentrarci nella risoluzione dei problemi, è fondamentale comprendere i ruoli di questi due strumenti principali:
systemctl: Questo comando è l'utilità centrale per controllare e interrogare il gestore di sistema e servizisystemd. Ti permette di avviare, fermare, riavviare, controllare lo stato e abilitare/disabilitare i servizi.journalctl: Questo comando viene utilizzato per interrogare il journal di systemd, che è un sistema di logging centralizzato. Raccoglie log dal kernel, dai servizi di sistema e dalle applicazioni, fornendo una visione unificata degli eventi di sistema.journalctlè prezioso per capire perché un servizio è fallito o si è comportato in modo inaspettato.
Scenari comuni di risoluzione dei problemi e soluzioni
Esploriamo i problemi tipici e come affrontarli:
1. Servizio non riuscito ad avviarsi
Questo è forse il problema più comune. Provi ad avviare un servizio e fallisce immediatamente.
Passo 1: Controlla lo stato del servizio
Usa systemctl status per ottenere una panoramica immediata dello stato del servizio e delle voci di log recenti.
sudo systemctl status apache2.service
Output previsto (illustrativo - il tuo potrebbe variare):
● apache2.service - The Apache HTTP Server
Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: enabled)
Active: **failed** (result: exit-code) since Tue 2023-10-27 10:00:00 UTC; 1min ago
Docs: https://httpd.apache.org/docs/2.4/
Process: 12345 ExecStart=/usr/sbin/apachectl start (code=exited, status=1/FAILURE)
Main PID: 12345 (code=exited, status=1/FAILURE)
Oct 27 10:00:00 your-server systemd[1]: Starting The Apache HTTP Server...
Oct 27 10:00:00 your-server apachectl[12345]: AH00526: Syntax error on line 123 of /etc/apache2/apache2.conf:
Oct 27 10:00:00 your-server apachectl[12345]: Invalid Mutex directory in argument file: '/var/run/apache2/'
Oct 27 10:00:00 your-server systemd[1]: apache2.service: Main process exited, code=exited, status=1/FAILURE
Oct 27 10:00:00 your-server systemd[1]: **Failed** to start The Apache HTTP Server.
Oct 27 10:00:00 your-server systemd[1]: apache2.service: Unit entered failed state.
Analisi: L'output di systemctl status mostra chiaramente Active: failed e fornisce un frammento del messaggio di errore: Invalid Mutex directory in argument file: '/var/run/apache2/'. Questo suggerisce un problema di configurazione.
Passo 2: Indaga sui log con journalctl
Per informazioni più dettagliate, usa journalctl per visualizzare i log specifici per il servizio fallito. Il flag -u specifica l'unità (servizio).
sudo journalctl -u apache2.service -xe
-u apache2.service: Filtra i log per l'unitàapache2.service.-x: Aggiunge spiegazioni per alcuni messaggi di log.-e: Salta alla fine del journal, mostrando le voci più recenti.
Risultati potenziali: L'output di journalctl potrebbe rivelare più contesto sull'errore di configurazione, problemi di permessi o problemi di dipendenza.
Passo 3: Controlla i file di configurazione
In base al messaggio di errore, esamina i file di configurazione pertinenti. Nell'esempio sopra, punta a /etc/apache2/apache2.conf e alla directory /var/run/apache2/.
sudo nano /etc/apache2/apache2.conf
Soluzione: Problemi come questo spesso derivano da una directory di runtime mancante, una modifica del pacchetto o un file di configurazione che fa riferimento a un percorso che non esiste più. Non creare ciecamente directory da un esempio su Internet. Prima conferma cosa si aspetta l'applicazione sulla tua distribuzione, poi correggi il percorso mancante o la configurazione. Una possibile riparazione potrebbe assomigliare a questa:
sudo mkdir -p /var/run/apache2/
sudo chown www-data:www-data /var/run/apache2/
sudo systemctl start apache2.service
Se l'errore menziona un problema di sintassi, esegui il test di configurazione dell'applicazione stessa prima di riavviare di nuovo:
sudo apachectl configtest
sudo nginx -t
sudo sshd -t
I validatori specifici dell'applicazione rilevano errori che systemd non può comprendere. Systemd sa se il processo è terminato. Non sa se il tuo blocco server di Nginx punta al file di certificato sbagliato o se una direttiva Apache appartiene a un contesto diverso.
2. Il servizio è in esecuzione ma non risponde
A volte, systemctl status mostra un servizio come active (running), ma non sta svolgendo la funzione prevista (ad esempio, un server web non serve pagine).
Passo 1: Verifica lo stato del servizio e il PID
Conferma che sia effettivamente in esecuzione e abbia un ID di processo (PID).
sudo systemctl status nginx.service
Se mostra active (running), annota il PID.
Passo 2: Esamina i log del servizio per errori
Anche se in esecuzione, il servizio potrebbe incontrare errori interni che gli impediscono di funzionare correttamente.
sudo journalctl -u nginx.service -f
-f: Segue l'output del log in tempo reale. Questo è utile se puoi attivare il problema (ad esempio, prova ad accedere alla pagina web) mentrejournalctlè in esecuzione.
Passo 3: Controlla i log specifici dell'applicazione
Molti servizi scrivono i propri log oltre al journal di systemd. Per server web come Nginx o Apache, controlla le loro tipiche posizioni dei log (ad esempio, /var/log/nginx/error.log, /var/log/apache2/error.log).
sudo tail -n 50 /var/log/nginx/error.log
Passo 4: Controlla l'utilizzo delle risorse
Un sistema sovraccarico può causare la mancata risposta dei servizi.
top
htop
free -h
Cerca un elevato utilizzo di CPU, memoria o I/O del disco da parte dei processi del servizio.
Controlla anche se il servizio è in ascolto dove ti aspetti:
sudo ss -ltnp
sudo ss -lunp
Per un servizio web, vedere nginx attivo in systemctl è solo metà della storia. Devi ancora sapere se è vincolato a 0.0.0.0:80, 127.0.0.1:8080, un socket IPv6 o nessun socket. Una regola del firewall, una mancata corrispondenza del proxy inverso o un indirizzo di bind errato possono far sembrare un processo sano rotto dall'esterno.
Soluzione: Se i log indicano problemi o le risorse sono sotto sforzo, potresti aver bisogno di:
- Ottimizzare le configurazioni.
- Riavviare il servizio (
sudo systemctl restart <nome_servizio>.service). - Investigare i problemi di risorse di sistema sottostanti.
- Aumentare le risorse di sistema se necessario.
3. Il servizio si ferma inaspettatamente
Se un servizio che era in esecuzione si ferma improvvisamente, spesso è dovuto a un'eccezione non gestita o a un timeout del watchdog.
Passo 1: Controlla la cronologia recente con journalctl
Usa journalctl per vedere cosa è successo appena prima che il servizio si fermasse. I flag --since e --until possono essere utili se conosci l'ora approssimativa.
sudo journalctl -u <nome_servizio>.service --since "1 hour ago"
Oppure, per vedere tutti i log relativi al servizio dall'ultimo avvio:
sudo journalctl -u <nome_servizio>.service -b
Passo 2: Cerca core dump o rapporti di crash
Se il servizio è andato in crash, il sistema potrebbe aver generato un core dump o un rapporto di crash.
ls -l /var/crash/
Passo 3: Rivedi il file dell'unità di servizio di systemd
Esamina il file dell'unità del servizio (di solito in /etc/systemd/system/ o /lib/systemd/system/) per le direttive Restart= e le impostazioni WatchdogSec=. Una configurazione Restart= errata o un WatchdogSec= troppo breve potrebbero causare riavvii o fallimenti imprevisti.
systemctl cat <nome_servizio>.service
Soluzione: Affronta la causa principale identificata nei log. Ciò potrebbe comportare la correzione di bug del codice, la regolazione dei parametri del file dell'unità systemd o l'aumento dei limiti delle risorse.
Se vedi riavvii ripetuti, controlla se systemd ha limitato la frequenza dell'unità:
systemctl status <nome_servizio>.service
journalctl -u <nome_servizio>.service --since "30 minutes ago"
I messaggi su Start request repeated too quickly di solito significano che il servizio è andato in crash più volte in una breve finestra. Dopo aver risolto il problema sottostante, cancella lo stato di fallimento:
sudo systemctl reset-failed <nome_servizio>.service
sudo systemctl start <nome_servizio>.service
4. Problemi con systemctl enable o systemctl disable
Sebbene non sia un fallimento in fase di esecuzione, possono verificarsi problemi nell'abilitazione o disabilitazione dei servizi.
Problema: Un servizio è abilitato ma non si avvia all'avvio, o viceversa.
Controlla lo stato:
sudo systemctl is-enabled <nome_servizio>.service
Questo comando restituirà enabled o disabled.
Risoluzione dei problemi:
- Assicurati che il file dell'unità di servizio stesso sia valido e posizionato correttamente (ad esempio,
/etc/systemd/system/). - Dopo aver apportato modifiche a un file di unità, esegui sempre
sudo systemctl daemon-reload. - Controlla i log per il servizio (
journalctl -u <nome_servizio>.service) per eventuali errori di avvio che potrebbero impedirgli di diventare attivo anche se abilitato.
Suggerimenti per una risoluzione dei problemi efficace
- Inizia con
systemctl status: Inizia sempre da qui. Fornisce un'istantanea rapida e spesso ti indica la giusta direzione. - Usa
journalctl -u <servizio>: Questo è il tuo strumento principale per capire perché sta succedendo qualcosa. - Flag
-fconjournalctl: Estremamente utile per il monitoraggio in tempo reale quando si cerca di riprodurre un problema. systemctl restart <servizio>: Dopo aver apportato modifiche alla configurazione, riavvia sempre il servizio per applicarle.systemctl daemon-reload: Fondamentale dopo aver modificato qualsiasi file di unità.service.- Controlla le dipendenze: A volte un servizio fallisce perché un servizio da cui dipende non è stato avviato o sta fallendo a sua volta.
systemctl statusspesso lo mostrerà. - Permessi: Molti fallimenti dei servizi sono dovuti a permessi errati di file o directory. Assicurati che l'utente con cui viene eseguito il servizio abbia l'accesso necessario.
- Problemi di rete: Se il servizio si basa sulla rete, controlla la connettività di rete, le regole del firewall e la disponibilità delle porte.
Un ordine di risoluzione dei problemi che regge
Quando la pressione è alta, usa sempre lo stesso ordine:
systemctl status <servizio>.service
journalctl -u <servizio>.service -b --no-pager
systemctl cat <servizio>.service
systemctl list-dependencies <servizio>.service
Inizia con lo stato corrente, poi leggi i log dall'avvio corrente, poi ispeziona l'unità esattamente come la vede systemd, poi controlla le dipendenze. Se il servizio è rivolto alla rete, aggiungi ss -ltnp e un test curl o client locale. Se legge un file di configurazione, esegui il validatore di configurazione del servizio stesso.
Il punto è evitare riavvii casuali. Riavviare può essere una correzione valida dopo una modifica della configurazione o un processo bloccato, ma distrugge anche le prove. Leggi abbastanza del journal prima in modo da sapere cosa stai cambiando e perché.
Leggere l'output del journal senza perdersi
journalctl può essere rumoroso, specialmente su server occupati. Inizia in modo ristretto, poi allarga solo quando necessario.
Per un servizio nell'avvio corrente:
journalctl -u <servizio>.service -b --no-pager
Per gli ultimi minuti:
journalctl -u <servizio>.service --since "15 minutes ago" --no-pager
Per l'avvio precedente:
journalctl -u <servizio>.service -b -1 --no-pager
Quella vista dell'avvio precedente è utile quando un servizio è fallito durante l'avvio e poi si è ripreso, o quando l'intera macchina è stata riavviata prima che potessi ispezionarla. Puoi elencare gli avvii con:
journalctl --list-boots
Se il servizio registra campi strutturati o righe lunghe, usa timestamp ISO brevi:
journalctl -u <servizio>.service -o short-iso --no-pager
Quando devi condividere i log, rimuovi segreti, token, hostname interni e dati dei clienti. I log dei servizi spesso includono impostazioni derivate dall'ambiente, URL, intestazioni o stringhe di connessione. Una buona abitudine di risoluzione dei problemi include la redazione prima di incollare l'output da qualsiasi parte.
Quando systemctl dice "Active" ma gli utenti vedono ancora un fallimento
Uno stato active (running) significa solo che systemd ha un processo che corrisponde alle aspettative dell'unità. Non prova che l'applicazione sia sana. Un'applicazione web può essere in esecuzione mentre restituisce HTTP 500. Un worker può essere attivo mentre è bloccato su un messaggio di coda errato. Un proxy di database può essere in esecuzione mentre tutte le connessioni backend falliscono.
Per i servizi di rete, testa dagli stessi livelli da cui dipendono i tuoi utenti:
curl -v http://127.0.0.1:8080/health
curl -v http://localhost/health
curl -v https://service.example.com/health
Questi tre controlli rispondono a domande diverse. Il primo controlla la porta dell'app locale. Il secondo può includere un proxy inverso locale. Il terzo controlla DNS, TLS, routing, regole del firewall e il percorso pubblico.
Per i servizi worker, guarda la cosa che consumano o producono. Un worker di coda potrebbe aver bisogno di un controllo della profondità della coda. Un servizio di backup potrebbe aver bisogno di un file di output recente. Un collettore di metriche potrebbe aver bisogno di una query sul backend delle metriche. systemctl ti dice se la supervisione funziona; i controlli dell'applicazione ti dicono se il servizio è utile.
Correggi una variabile alla volta
Quando un'unità fallisce dopo un deployment, è tentatore cambiare diverse cose e riavviare. Questo può nascondere la vera causa. Preferisci un cambiamento alla volta:
systemctl cat my-app.service
journalctl -u my-app.service --since "30 minutes ago" --no-pager
sudo systemctl edit my-app.service
sudo systemctl daemon-reload
sudo systemctl restart my-app.service
Poi controlla il risultato prima di cambiare la cosa successiva. Se il fallimento è un file mancante, correggi il percorso del file. Se è un errore di permesso, correggi la proprietà o la modalità. Se è una dipendenza, correggi la relazione dell'unità o il comportamento di ripetizione dell'applicazione. Una risoluzione dei problemi lenta e noiosa è spesso più veloce di un ciclo di riavvio con cinque modifiche non tracciate.