systemd-analyze: guida per analizzare il boot di Linux
Quando un computer Linux impiega molto tempo ad avviarsi, la prima domanda è quasi sempre la stessa:
Che cosa sta rallentando il boot?
Individuare la causa, però, non è sempre immediato. Il sistema operativo deve inizializzare il kernel, eventualmente l’initrd e una lunga serie di Unit e servizi, molti dei quali vengono avviati contemporaneamente.
Nel caso di systemd, abbiamo a disposizione uno strumento specifico per analizzare questo processo: systemd-analyze.
Il comando permette di ottenere informazioni sui tempi di avvio, individuare le Unit che hanno richiesto più tempo per essere inizializzate e analizzare la catena critica, cioè la sequenza di dipendenze che ha maggiormente influenzato il raggiungimento di un determinato Target.
Non si tratta quindi semplicemente di trovare “il servizio più lento”: systemd-analyze ci aiuta a capire come le diverse Unit interagiscono durante il boot.
Cosa imparerai
Al termine della guida saprai:
- utilizzare
systemd-analyzeper ottenere un riepilogo del boot; - individuare le Unit che richiedono più tempo;
- interpretare
systemd-analyze blame; - utilizzare
critical-chain; - generare un grafico temporale del boot;
- capire perché il servizio più lento non è necessariamente il principale responsabile del ritardo;
- costruire un semplice metodo di analisi del boot.
Che cos’è systemd-analyze?
systemd-analyze è uno strumento della suite systemd dedicato all’analisi e al debugging del system manager.
Tra le sue funzioni troviamo l’analisi delle prestazioni del boot, la visualizzazione delle dipendenze e la verifica delle Unit.
La forma più semplice del comando è:
systemd-analyze
oppure:
systemd-analyze time
Il risultato può essere simile a:
Startup finished in 2.584s (kernel)
+ 19.176s (initrd)
+ 47.847s (userspace)
= 1min 9.608s
multi-user.target reached after 47.820s in userspace
Le cifre cambieranno naturalmente da sistema a sistema.
È importante però capire che questi tempi non rappresentano necessariamente il momento in cui ogni servizio ha terminato completamente tutte le proprie attività: il comando misura specifici punti del processo di avvio e, per il tempo userspace, arriva al momento in cui i servizi sono stati avviati, non necessariamente quando ogni processo ha terminato ogni fase di inizializzazione.
Il primo comando: systemd-analyze time
Cominciamo quindi da:
systemd-analyze time
È il punto di partenza della nostra analisi.
Possiamo immaginare il boot come una serie di fasi:
Firmware
│
▼
Kernel
│
▼
Initrd
│
▼
Userspace / systemd
│
▼
Target
systemd-analyze time ci aiuta a capire quanto tempo viene impiegato nelle diverse fasi che systemd può misurare.
Se il tempo è particolarmente elevato nella fase userspace, possiamo procedere con un’analisi più dettagliata.
Quali Unit stanno rallentando l’avvio?
Il comando probabilmente più conosciuto di systemd-analyze è:
systemd-analyze blame
L’output è una lista delle Unit ordinate in base al tempo impiegato per la loro inizializzazione.
Un esempio semplificato:
12.345s NetworkManager-wait-online.service
7.812s docker.service
4.215s plymouth-quit-wait.service
3.102s systemd-journald.service
2.341s cron.service
A prima vista potremmo essere tentati di concludere:
“NetworkManager-wait-online è il problema.”
Non necessariamente.
Ed è qui che bisogna prestare attenzione.
blame non racconta tutta la storia
Il tempo mostrato da systemd-analyze blame è utile, ma non deve essere interpretato come una classifica assoluta dei “colpevoli” del boot.
Una Unit può risultare lenta perché sta aspettando un’altra Unit.
Inoltre, systemd avvia molte Unit in parallelo.
Immaginiamo:
┌── service A ── 10s
Boot ──────┼── service B ── 2s
└── service C ── 1s
Il fatto che service A richieda 10 secondi non significa automaticamente che il boot complessivo sia stato ritardato di 10 secondi.
Potrebbe infatti essere stato avviato parallelamente ad altre Unit e non trovarsi lungo il percorso che determina il raggiungimento del Target.
Per questo, dopo blame, è fondamentale utilizzare un altro comando.
La catena critica: critical-chain
Eccoci al cuore dell’analisi.
systemd-analyze critical-chain
Questo comando mostra la catena critica del boot, evidenziando la sequenza di Unit che ha maggiormente condizionato il raggiungimento del Target analizzato.
Un output semplificato potrebbe essere:
graphical.target
└─multi-user.target
└─docker.service
└─network-online.target
└─NetworkManager-wait-online.service
La cosa interessante non è soltanto sapere quale servizio è lento.
Vogliamo capire:
Quale sequenza di dipendenze sta impedendo al sistema di arrivare prima al Target?
È una domanda molto diversa.
critical-chain e blame insieme
A questo punto possiamo stabilire una procedura molto semplice.
1. Misuriamo il boot
systemd-analyze time
2. Cerchiamo le Unit più lente
systemd-analyze blame
3. Analizziamo la catena critica
systemd-analyze critical-chain
Il flusso diventa:
Quanto dura il boot?
│
▼
systemd-analyze time
│
▼
Quali Unit sono lente?
│
▼
systemd-analyze blame
│
▼
Qual è la catena critica?
│
▼
systemd-analyze critical-chain
Questa sequenza è già sufficiente per effettuare una prima analisi su moltissimi sistemi.
Analizzare una Unit specifica
Possiamo anche chiedere a critical-chain di concentrarsi su una determinata Unit:
systemd-analyze critical-chain docker.service
Questo può essere utile quando abbiamo già individuato un servizio interessante e vogliamo capire quali dipendenze si trovano prima di esso.
Creare un grafico del boot
Per un’analisi ancora più intuitiva possiamo utilizzare:
systemd-analyze plot > boot.svg
Viene generato un file SVG contenente una rappresentazione temporale dell’avvio.
Possiamo quindi aprirlo con il browser:
xdg-open boot.svg
oppure semplicemente aprire il file con il proprio visualizzatore preferito.
Il grafico permette di visualizzare quando le diverse Unit vengono attivate e quanto tempo richiedono, rendendo più semplice individuare sovrapposizioni, attese e colli di bottiglia.
Un esempio pratico
Immaginiamo che il nostro sistema sembri lento ad avviarsi.
Cominciamo:
systemd-analyze time
Otteniamo:
Startup finished in 8.4s
Non sappiamo ancora cosa stia causando il ritardo.
Passiamo quindi a:
systemd-analyze blame
e troviamo:
7.2s NetworkManager-wait-online.service
3.1s docker.service
2.8s snapd.service
Potremmo essere tentati di disabilitare immediatamente NetworkManager-wait-online.service.
Non facciamolo.
Prima analizziamo:
systemd-analyze critical-chain
Se scopriamo che il servizio di attesa della rete si trova effettivamente nella catena critica, allora abbiamo trovato un elemento che merita un’indagine.
A quel punto possiamo chiederci:
- il sistema ha davvero bisogno di aspettare la rete durante il boot?
- quali servizi richiedono
network-online.target? - il servizio sta aspettando una rete che non sarà disponibile?
- la configurazione di rete è corretta?
Il comando non ci dice semplicemente “disabilita questo servizio”.
Ci fornisce gli elementi per capire perché sta accadendo qualcosa.
Ed è questa la differenza tra ottimizzazione e semplice eliminazione di servizi.
Visualizzare le dipendenze
systemd-analyze permette anche di generare grafi delle dipendenze utilizzando il comando:
systemd-analyze dot
L’output è in formato Graphviz DOT.
Possiamo quindi generare un SVG, ad esempio:
systemd-analyze dot | dot -Tsvg > systemd.svg
Questo tipo di visualizzazione è particolarmente interessante quando stiamo studiando sistemi complessi con molte dipendenze tra Unit.
Per un’amministrazione quotidiana, tuttavia, critical-chain rimane generalmente più immediato.
Un metodo pratico per ottimizzare il boot
A questo punto possiamo trasformare i comandi che abbiamo visto in un vero metodo di lavoro.
1. Misura
systemd-analyze time
Prima di modificare qualsiasi cosa, dobbiamo sapere da dove partiamo.
2. Individua
systemd-analyze blame
Cerchiamo le Unit che richiedono più tempo.
3. Correla le Unit
systemd-analyze critical-chain
Verifichiamo se quelle Unit si trovano realmente lungo la catena critica.
4. Approfondisci
Utilizziamo:
systemctl status nome.service
e:
journalctl -u nome.service
per capire cosa sta succedendo.
5. Modifica
Solo a questo punto valutiamo se intervenire sulla configurazione.
6. Misura nuovamente
Dopo la modifica:
systemd-analyze time
e confrontiamo il risultato con quello iniziale.
Attenzione alle ottimizzazioni “facili”
Uno degli errori più comuni è cercare di ridurre il numero di servizi avviati senza sapere cosa fanno.
Ad esempio:
systemctl disable servizio.service
può apparentemente ridurre i tempi di boot.
Ma se quel servizio è necessario a una funzione del sistema, abbiamo semplicemente scambiato qualche secondo di boot con un problema successivo.
Lo stesso vale per la modifica indiscriminata delle dipendenze.
Un boot più veloce non è automaticamente un boot migliore.
L’obiettivo dovrebbe essere eliminare attese inutili, correggere configurazioni problematiche e avviare soltanto ciò che serve davvero.
Un comando interessante: systemd-analyze verify
C’è un’altra funzione di systemd-analyze che vale la pena conoscere:
systemd-analyze verify nome.service
È particolarmente utile quando stiamo sviluppando o modificando una Unit.
Permette di verificare la correttezza della configurazione e può segnalare diversi problemi, come direttive sconosciute o dipendenze mancanti.
È quindi un ottimo complemento al lavoro che abbiamo fatto nell’articolo dedicato alla creazione dei file .service.
I comandi da ricordare
| Comando | Funzione |
|---|---|
systemd-analyze | Riepilogo dei tempi di boot |
systemd-analyze time | Analizza i tempi di avvio |
systemd-analyze blame | Mostra le Unit ordinate per tempo di inizializzazione |
systemd-analyze critical-chain | Mostra la catena critica |
systemd-analyze plot | Genera un grafico SVG del boot |
systemd-analyze dot | Genera un grafo delle dipendenze |
systemd-analyze verify | Verifica una Unit |
systemd-analyze calendar | Verifica espressioni temporali per i Timer |
Quest’ultimo comando è particolarmente interessante perché collega questo articolo al precedente: systemd-analyze calendar permette infatti di interpretare e verificare le espressioni utilizzate da OnCalendar= nei Timer.
Errori comuni
Guardare soltanto blame
È probabilmente l’errore più frequente.
blame è utile, ma non racconta da solo la relazione tra tempi e dipendenze.
Disabilitare il servizio più lento
Il servizio più lento potrebbe non trovarsi sulla catena critica.
Ottimizzare senza misurare
Prima:
systemd-analyze time
Dopo:
systemd-analyze time
Altrimenti non sappiamo se la modifica abbia realmente prodotto un miglioramento.
Confondere tempo di attivazione e impatto sul boot
Le Unit possono essere avviate in parallelo. Una Unit lenta non implica necessariamente un ritardo equivalente dell’intero sistema.
Conclusioni
systemd-analyze è uno degli strumenti più utili per comprendere cosa accade durante l’avvio di una distribuzione Linux moderna.
Il suo utilizzo diventa particolarmente efficace quando smettiamo di considerare il boot come una semplice sequenza:
servizio 1
↓
servizio 2
↓
servizio 3
e iniziamo a considerarlo per quello che è realmente: un insieme di Unit con dipendenze che possono essere attivate anche in parallelo.
Per una prima analisi possiamo ricordare soltanto tre comandi:
systemd-analyze time
systemd-analyze blame
systemd-analyze critical-chain
Il primo ci dice quanto dura il boot, il secondo ci aiuta a capire quali Unit richiedono più tempo, mentre il terzo ci mostra quale catena di dipendenze condiziona maggiormente l’avvio.
Ed è proprio questa combinazione che trasforma systemd-analyze da semplice comando diagnostico in uno strumento concreto di troubleshooting e ottimizzazione.
Nel prossimo articolo della serie systemd arriveremo al troubleshooting vero e proprio: vedremo cosa fare quando un servizio non parte, come leggere systemctl status, come interrogare il journal con journalctl e come procedere dall’errore alla soluzione.
LICENZA E CONDIZIONI D’USO
Questo How-to è rilasciato sotto licenza Creative Commons Attribution-NonCommercial 3.0 Italy.
CONTATTI DELL’AUTORE
Marco Ciammella marco@orvietolinux.it
Orvieto Linux User Group info@orvietolinux.it