Risoluzione dei Problemi di Avvio di Systemd: Problemi Comuni e Soluzioni

Diagnostica i problemi di avvio di systemd con journalctl, controlli delle unità fallite, target di ripristino, correzioni di fstab, revisione delle dipendenze e debug di initramfs.

Risoluzione dei Problemi di Avvio di Systemd: Problemi Comuni e Soluzioni

I problemi di avvio di Linux sembrano urgenti perché spesso si perdono prima gli strumenti comodi. SSH potrebbe essere giù, il login grafico potrebbe non apparire mai e la console potrebbe farti cadere in modalità di emergenza con un messaggio che sembra peggiore di quello che è. Con i problemi di avvio di systemd, la prima mossa migliore non è indovinare. Trova il punto in cui l'avvio si è fermato, poi lavora all'indietro attraverso i log delle unità, i fallimenti di mount, gli errori di dipendenza o i messaggi precoci del kernel.

Questa guida si concentra sui fallimenti che accadono una volta che il kernel ha avviato systemd come PID 1, più alcuni problemi vicini che sembrano fallimenti di systemd dalla console: voci errate in /etc/fstab, problemi di initramfs ed errori del bootloader.

Comprendere il Processo di Avvio di Systemd

Systemd gestisce il processo di avvio di Linux attraverso un sistema di "unità". Queste unità descrivono varie risorse e servizi di sistema, come servizi (.service), punti di mount (.mount), dispositivi (.device) e target (.target). I target sono unità speciali che raggruppano altre unità e rappresentano punti di sincronizzazione o stati specifici durante il processo di avvio, come multi-user.target (il tradizionale runlevel 3) o graphical.target (runlevel 5).

Il processo di avvio tipicamente coinvolge:

  1. Inizializzazione del Kernel: Il kernel carica e inizializza l'hardware.
  2. Fase Initramfs: Viene caricato un filesystem RAM iniziale, che include driver e strumenti essenziali per montare il filesystem root.
  3. Avvio di Systemd: Systemd subentra come PID 1, avviando il default.target (che spesso è un collegamento simbolico a multi-user.target o graphical.target).
  4. Attivazione delle Unità: Systemd legge i file delle unità, risolve le dipendenze e avvia servizi e mount in modo altamente parallelo.

I problemi di avvio possono verificarsi in qualsiasi di queste fasi, ma questa guida si concentra principalmente sui problemi che si manifestano una volta che systemd è stato avviato.

Triage Iniziale: Accesso ai Log di Avvio

Quando il sistema non riesce ad avviarsi correttamente, il primo e più critico passo è accedere ai log di avvio. Questi log forniscono indizi su cosa è andato storto. Se il sistema non si avvia in un ambiente grafico o nemmeno in una TTY standard, dovrai utilizzare metodi alternativi.

1. Usare journalctl (Dalla Modalità di Ripristino/Emergenza o da Supporto Live)

journalctl è l'utilità per interrogare il journal di systemd. Se il sistema può avviarsi in modalità di ripristino o modalità di emergenza, o se stai usando un USB/CD live per accedere al disco, journalctl è il tuo strumento principale.

Per visualizzare i log dell'avvio precedente:

journalctl -b -1

Per visualizzare tutti i messaggi dall'avvio del sistema:

journalctl -b

Per visualizzare i log relativi alle unità fallite:

journalctl -b -p err..emerg # Mostra errori, critici, allarmi, messaggi di emergenza
journalctl -b --since "-5min" # Mostra i log degli ultimi 5 minuti dell'avvio corrente

Se stai usando un ambiente live, non hai sempre bisogno di un chroot completo solo per leggere i log. Monta il sistema installato e punta journalctl ad esso:

mount /dev/mapper/vg0-root /mnt
journalctl --directory=/mnt/var/log/journal -b -1

Su sistemi senza journal persistenti, i log di avvio più vecchi potrebbero non esistere sotto /var/log/journal. In tal caso, controlla i log specifici della distribuzione sotto /var/log, o riproduci l'avvio dopo aver abilitato il journal persistente quando il sistema è abbastanza sano per farlo.

2. Usare dmesg

dmesg mostra il buffer circolare del kernel, che contiene messaggi del kernel durante l'avvio. Questo è particolarmente utile per problemi che si verificano molto presto nel processo di avvio, prima che systemd abbia preso completamente il controllo.

dmesg

3. Esaminare lo Stato delle Unità

Una volta in una shell utilizzabile (modalità di ripristino, modalità di emergenza o ambiente live con chroot), puoi controllare lo stato di tutte le unità systemd.

systemctl --failed

Questo comando elenca tutte le unità che non sono riuscite ad avviarsi. Per informazioni dettagliate su una specifica unità fallita, usa:

systemctl status <nome_unità>.service

E per visualizzare le sue voci di journal specifiche:

journalctl -u <nome_unità>.service -b

Problemi Comuni di Avvio di Systemd e Soluzioni

1. Servizi Falliti e Fallimenti di Unità

Problema: Un servizio critico non riesce ad avviarsi, impedendo al sistema di raggiungere il target desiderato (es., multi-user.target). Questo spesso si manifesta con il sistema che cade in modalità di emergenza.

Sintomi: systemctl --failed mostra una o più unità con stato "failed". journalctl -u <nome_unità>.service rivela messaggi di errore che indicano perché il servizio non ha potuto avviarsi.

Cause Comuni:

  • Configurazione Errata: Errore di battitura in un file di configurazione, percorsi errati, dipendenze mancanti.
  • File/Dipendenze Mancanti: Un servizio tenta di accedere a un file o directory che non esiste o è inaccessibile.
  • Esaurimento Risorse: Il servizio tenta di allocare troppa memoria o altre risorse.
  • Problemi di Permessi: Il servizio non ha i permessi necessari per leggere/scrivere file o eseguire comandi.

Soluzioni:

  1. Identifica l'Unità Fallita: Usa systemctl --failed.
  2. Ispeziona i Log: Esegui journalctl -u <nome_unità>.service -b per messaggi di errore dettagliati.
  3. Correggi la Configurazione: Modifica il file di configurazione del servizio (es., /etc/systemd/system/<nome_unità>.service o file in /etc/). Presta attenzione alle direttive ExecStart, WorkingDirectory, User, Group, Environment.
  4. Controlla le Dipendenze: Assicurati che tutte le direttive Wants=, Requires=, After=, Before= siano specificate correttamente e che i servizi richiesti siano abilitati.
  5. Riavvia e Riabilita: Dopo aver apportato modifiche, esegui systemctl daemon-reload, poi prova systemctl start <nome_unità>.service e systemctl enable <nome_unità>.service.

Esempio: Un servizio web personalizzato mywebapp.service fallisce perché il suo database non è disponibile.

# Controlla lo stato
systemctl status mywebapp.service

# Controlla i log per indizi
journalctl -u mywebapp.service -b

# Modifica il file dell'unità (es., in /etc/systemd/system/mywebapp.service)
# Aggiungi/modifica la direttiva After= per assicurarti che il database parta prima
# es., After=postgresql.service mysql.service

# Ricarica systemd e riprova
systemctl daemon-reload
systemctl start mywebapp.service
systemctl enable mywebapp.service # Assicurati che parta al prossimo avvio

2. Problemi di Filesystem

Problema: Filesystem corrotti o voci errate in /etc/fstab possono impedire al sistema di montare partizioni critiche, portando alla modalità di emergenza.

Sintomi: Messaggi di errore su fallimenti di fsck, errori di mount, o il sistema che cade in modalità di emergenza con un messaggio come "Give root password for maintenance (or type Control-D to continue)".

Cause Comuni:

  • Filesystem Sporco: Spegnimento improprio, perdita di alimentazione.
  • /etc/fstab Errato: Errore di battitura in UUID/percorso dispositivo, tipo di filesystem sbagliato, noauto mancante per mount non critici.
  • Guasto Hardware: Corruzione del disco.

Soluzioni:

  1. Accedi alla Modalità di Emergenza: Se richiesto, inserisci la password di root.
  2. Controlla /etc/fstab: Rivedi attentamente /etc/fstab per eventuali errori. Commenta temporaneamente le righe sospette con #.
  3. Esegui fsck con attenzione: Controlla e ripara manualmente i filesystem solo quando sono smontati, o montati in sola lettura in un contesto di manutenzione dove la tua distribuzione lo documenta come sicuro. Per una partizione non root:
    umount /dev/sdb1
    fsck -f /dev/sdb1
    
    Se il filesystem root necessita di riparazione, avvia da supporto live o da un ambiente di ripristino ed esegui fsck da lì. Evita fsck -y come prima mossa su dischi importanti; rivedi i prompt a meno che tu non abbia già un backup o capisca il danno.
  4. Riavvia: Dopo aver apportato modifiche o eseguito fsck, prova a riavviare.

3. Conflitti di Dipendenza e Ordinamento delle Unità

Problema: I servizi partono nell'ordine sbagliato, o le unità hanno dipendenze contrastanti, portando a deadlock o fallimenti.

Sintomi: Servizi che vanno in timeout, servizi che falliscono perché le loro dipendenze non sono pronte, systemd-analyze plot che mostra lunghe catene o cicli.

Cause Comuni:

  • Direttive Wants=, Requires=, After=, Before= configurate male nei file delle unità.
  • Unità che si aspettano risorse non ancora disponibili.

Soluzioni:

  1. Analizza la Sequenza di Avvio: Usa systemd-analyze per visualizzare il processo di avvio.

    • systemd-analyze blame: Mostra i servizi ordinati per tempo di avvio, evidenziando le unità lente.
    • systemd-analyze critical-chain: Mostra il percorso critico delle unità che influenzano direttamente il tempo di avvio complessivo.
    • systemd-analyze plot > boot.svg: Genera un'immagine SVG dell'intero grafo delle dipendenze di avvio, inestimabile per problemi complessi.
  2. Ispeziona le Dipendenze delle Unità: Usa systemctl list-dependencies <nome_unità> per vedere cosa richiede un'unità e cosa dipende da essa.

  3. Regola le Direttive del File dell'Unità:

    • After=, Before=: Controllano l'ordinamento delle unità. Se A.service ha After=B.service, A partirà dopo B (se B viene avviato). Usa After= per la maggior parte delle esigenze di ordinamento.
    • Wants=: Esprime una dipendenza debole. Se A.service Wants=B.service, B verrà avviato quando A parte, ma A continuerà anche se B fallisce.
    • Requires=: Esprime una dipendenza forte. Se A.service Requires=B.service, B viene attirato quando A parte, e A fallisce se B non può essere avviato. Se B viene fermato esplicitamente, anche A viene fermato.
    • Conflicts=: Assicura che un'unità specifica venga fermata se l'unità corrente viene avviata, e viceversa.
    • PartOf=: Collega il ciclo di vita di un'unità a un'altra (es., se uno slice viene fermato, tutte le unità PartOf di esso vengono fermate).

    Consiglio: Preferisci sempre After= e Wants= per la maggior parte delle dipendenze per evitare di creare un accoppiamento stretto che potrebbe portare a deadlock o cascate di fallimenti.

4. Panico del Kernel / Problemi di Initramfs

Problema: Il sistema non riesce ad avviarsi molto presto, spesso prima che systemd prenda completamente il controllo, mostrando messaggi come "Kernel panic - not syncing" o relativi a dracut o initramfs.

Sintomi: Fallimento di avvio precoce, spesso con un muro di testo che mostra stack trace o messaggi su dispositivo root mancante, /dev/root non trovato, ecc.

Cause Comuni:

  • Moduli del Kernel Mancanti: Initramfs non contiene i driver necessari per il filesystem root (es., LVM, RAID, controller disco specifici).
  • Kernel/Initramfs Corrotti: I file sono danneggiati.
  • Parametri del Kernel Errati: Il parametro root= in GRUB punta al dispositivo sbagliato.

Soluzioni:

  1. Ricostruisci Initramfs: Questa è una correzione comune. Avvia in un ambiente live o con un altro kernel, fai chroot nel tuo sistema e ricostruisci l'initramfs.
    # Esempio per Dracut (Fedora/RHEL/CentOS)
    dracut -f -v /boot/initramfs-$(uname -r).img $(uname -r)
    
    # Esempio per mkinitcpio (Arch Linux)
    mkinitcpio -P
    
    # Esempio per update-initramfs (Debian/Ubuntu)
    update-initramfs -u -k all
    
  2. Verifica la Configurazione di GRUB: Controlla /boot/grub/grub.cfg (o /etc/default/grub se lo rigeneri) per il parametro root= corretto e il percorso initrd.
  3. Parametri del Kernel: Se sospetti che un modulo specifico manchi o causi problemi, puoi provare ad aggiungere parametri del kernel in GRUB (es., rd.break per entrare nella shell di initramfs per il debug).

5. Problemi di GRUB/Bootloader

Problema: Il sistema non raggiunge nemmeno il punto in cui il kernel viene caricato, o si blocca al menu di GRUB.

Sintomi: "Nessun dispositivo di avvio trovato", prompt di ripristino di GRUB, o GRUB non riesce a caricare il kernel.

Cause Comuni:

  • Bootloader corrotto.
  • Configurazione GRUB errata che punta a kernel/initramfs inesistenti.
  • Impostazioni BIOS/UEFI che impediscono il corretto ordine di avvio.

Soluzioni:

  1. Reinstalla GRUB: Avvia da una USB live, fai chroot nel tuo sistema e reinstalla GRUB nel MBR/partizione EFI.
    # Esempio
    mount /dev/sdaX /mnt # Monta la partizione root
    
    mount /dev/sdaY /mnt/boot/efi # Se partizione EFI separata
    
    for i in /dev /dev/pts /proc /sys /run; do mount --bind $i /mnt$i; done
    chroot /mnt
    
    grub-install /dev/sda # Installa nel disco principale
    
    grub-mkconfig -o /boot/grub/grub.cfg # Rigenera la configurazione di GRUB
    
    exit
    umount -R /mnt
    reboot
    
  2. Controlla le Impostazioni BIOS/UEFI: Assicurati che il corretto drive di avvio sia prioritario.

Tecniche Avanzate di Risoluzione dei Problemi

Avviare in Modalità di Ripristino/Emergenza

Queste modalità forniscono un ambiente minimale per la risoluzione dei problemi. Per accedervi:

  1. Durante GRUB: Premi e per modificare la riga di comando del kernel.
  2. Individua la riga linux: Trova la riga che inizia con linux (o linuxefi).
  3. Aggiungi systemd.unit=rescue.target per la modalità di ripristino (la maggior parte dei servizi è spenta, shell single-user).
  4. Aggiungi systemd.unit=emergency.target per la modalità di emergenza (servizi minimi, spesso root in sola lettura).
  5. Premi Ctrl+X o F10 per avviare.

Usare rd.break per il Debug di Initramfs

Aggiungere rd.break alla riga di comando del kernel in GRUB ti farà cadere in una shell all'interno dell'initramfs prima che il filesystem root reale venga montato. Questo è estremamente utile per il debug di problemi di initramfs, come driver mancanti o problemi con la configurazione LVM/RAID.

Una volta nella shell di initramfs, puoi:

  • Ispezionare lsblk, mount.
  • Controllare i file mancanti in /sysroot.
  • Provare a montare manualmente il filesystem root.

Analizzare le Prestazioni di Avvio

Anche se non è strettamente un "fallimento", i tempi di avvio lenti possono indicare problemi sottostanti o configurazioni di servizi inefficienti.

  • systemd-analyze blame: Identifica i servizi che impiegano più tempo ad avviarsi.
  • systemd-analyze critical-chain: Comprendi il percorso critico delle dipendenze che influenzano il tempo di avvio complessivo.

Una Sequenza di Recupero Sicura

Quando sei alla console e la macchina è a metà avvio, mantieni la sequenza di recupero noiosa:

  1. Cattura l'errore esatto sullo schermo se puoi.
  2. Esegui systemctl --failed.
  3. Leggi journalctl -b -p err..alert --no-pager.
  4. Se un'unità è fallita, leggi journalctl -u nome-unità -b.
  5. Se un mount è fallito, ispeziona /etc/fstab, verifica gli UUID con blkid e commenta solo il mount non critico sospetto.
  6. Se il filesystem root o initramfs è coinvolto, passa a supporto live o modalità di ripristino prima di fare riparazioni invasive.
  7. Dopo le modifiche ai file delle unità, esegui systemctl daemon-reload e riavvia solo l'unità interessata quando possibile.

La maggior parte dei problemi di avvio di systemd non viene risolta cambiando molte cose contemporaneamente. Una linea di mount errata, un disco mancante, un servizio con un ExecStart= rotto o un errore di ordinamento lasciano una traccia abbastanza diretta. Segui quella traccia, fai una piccola riparazione e riavvia solo quando la shell corrente non può testare la correzione.

Usa questi strumenti per identificare i colli di bottiglia e ottimizzare l'avvio delle unità regolando le direttive After=, Requires=, TimeoutStartSec= o Type=.

Prevenzione e Migliori Pratiche

  • Testa le Modifiche: Prima di distribuire modifiche ai file delle unità in produzione, testale in un ambiente di staging.
  • Backup della Configurazione: Esegui regolarmente il backup di /etc/ o almeno dei file critici di /etc/systemd/system/.
  • Comprendi le Direttive delle Unità: Una solida comprensione delle pagine man di systemd.service(5) e systemd.unit(5) è inestimabile.
  • Usa File Drop-in: Invece di modificare direttamente i file delle unità in /lib/systemd/system/ (che possono essere sovrascritti dagli aggiornamenti), usa file drop-in (/etc/systemd/system/<nome_unità>.service.d/*.conf) per configurazioni personalizzate.
  • Mantieni i Kernel: Tieni sempre almeno un kernel vecchio e noto funzionante sul sistema per avviarti se un nuovo kernel causa problemi.

Conclusione

Risolvere i problemi di avvio di systemd richiede un approccio sistematico, a partire da un'efficace analisi dei log. Comprendendo l'architettura basata su unità di systemd e sfruttando strumenti come journalctl, systemctl e systemd-analyze, puoi individuare efficientemente la causa principale dei fallimenti di avvio, che si tratti di un servizio configurato male, un problema di filesystem o un complesso conflitto di dipendenze. La capacità di avviarsi in modalità di ripristino o emergenza, insieme a tecniche avanzate di debug, ti permette di riprendere il controllo del tuo sistema anche quando sembra completamente non reattivo. Con queste strategie e migliori pratiche, sarai ben equipaggiato per affrontare la maggior parte delle sfide di avvio di systemd e mantenere operazioni Linux stabili e affidabili.