Comprendere i Target di Systemd: Concetti Essenziali Spiegati

Comprendi i target di systemd, i target di avvio predefiniti, le mappature dei runlevel, l'isolamento, i target personalizzati e i comandi per la risoluzione dei problemi.

Comprendere i Target di Systemd: Concetti Essenziali Spiegati

I target di systemd sono più facili da capire se smetti di pensarli come servizi. Un servizio avvia un processo. Un target raggruppa unità in uno stato di sistema denominato. Quando una macchina si avvia in multi-user.target, systemd non sta avviando un programma chiamato "multi-utente". Sta cercando di raggiungere uno stato in cui le unità desiderate da quel target sono state avviate o almeno hanno avuto tentativi di avvio.

Questa distinzione aiuta quando si eseguono debug di problemi di avvio. Se graphical.target è lento, il target stesso è raramente il problema. Una delle unità di visualizzazione, login, rete, mount o applicazione inserite in quel target è lenta o fallisce. I target ti forniscono la mappa.

Cosa sono i Target di Systemd?

Nell'ecosistema systemd, un target è un tipo speciale di file unit (come i file .service o .socket) che svolge una funzione organizzativa critica. A differenza delle unità di servizio che definiscono come avviare o fermare un processo specifico, le unità target definiscono uno stato di sistema o una collezione di unità che dovrebbero essere attive insieme. Agiscono come punti di raggruppamento logico e punti di sincronizzazione per altre unità systemd.

Pensa ai target come tappe nel percorso operativo del sistema. Quando systemd si avvia, non lancia semplicemente un elenco di servizi in modo arbitrario; lavora per raggiungere un target specifico. Questo target, a sua volta, richiama tutti i servizi, socket, punti di mount e altri target necessari per raggiungere quello stato. Questo approccio basato sulle dipendenze garantisce un processo di avvio prevedibile ed efficiente.

Per chi ha familiarità con i vecchi sistemi init Linux come SysVinit, i target di systemd sono l'equivalente moderno dei runlevel. Mentre SysVinit aveva un insieme fisso di runlevel (ad esempio, runlevel 3 per la modalità testo multi-utente, runlevel 5 per la modalità grafica multi-utente), i target di systemd sono più flessibili. Sono nominati, non numerati, e puoi definire target personalizzati, offrendo maggiore granularità ed estensibilità.

Come Funzionano i Target: Raggruppamento e Dipendenze

I target raggiungono le loro capacità di raggruppamento e definizione dello stato attraverso dipendenze esplicite definite nei loro file unit. Le direttive principali utilizzate per questo sono Wants=, Requires=, After=, e Before=.

  • Wants=: Specifica dipendenze "deboli". Se target A Wants= unità B, systemd proverà ad avviare unità B quando target A viene attivato. Tuttavia, target A si avvierà comunque anche se unità B non riesce ad avviarsi. Questo è comunemente usato per raggruppare servizi correlati che sono desiderabili ma non strettamente essenziali.
  • Requires=: Specifica dipendenze "forti". Se target A Requires= unità B, allora unità B deve essere avviata con successo affinché target A si attivi. Se unità B fallisce, anche target A fallirà o non si avvierà. Questo è usato per dipendenze critiche.
  • After=: Definisce una dipendenza di ordinamento. Se target A ha After= unità B, allora target A si avvierà solo dopo che unità B si è avviata. Questo non implica una dipendenza dal successo, solo dall'ordine.
  • Before=: L'inverso di After=. Se target A ha Before= unità B, allora unità B si avvierà solo dopo che target A si è avviato.
  • Conflicts=: Assicura che certe unità non siano attive simultaneamente. Se target A Conflicts= unità B, allora attivare target A fermerà unità B se è in esecuzione, e viceversa.

Queste direttive permettono ai target di agire come orchestratori robusti, richiamando servizi e altri target secondo necessità e definendo l'ordine in cui dovrebbero avviarsi. Ad esempio, multi-user.target tipicamente Wants= network.target e vari altri servizi, assicurando che siano attivi quando il sistema raggiunge uno stato multi-utente.

Puoi ispezionare il contenuto di un file unit target per vedere le sue dipendenze:

systemctl cat multi-user.target

Questo comando restituirà il contenuto del file unit multi-user.target, mostrando la sua Description, Documentation, e, crucialmente, le sue direttive Wants=, Requires=, After=, e altre che definiscono cosa costituisce lo stato multi-utente.

Spiegazione dei Target Comuni di Systemd

Systemd fornisce una varietà di target predefiniti, ciascuno corrispondente a uno stato o funzionalità specifica del sistema. Comprenderli è cruciale per l'amministrazione del sistema:

  • default.target: Questo è il target più importante poiché definisce lo stato predefinito in cui il sistema si avvierà. Di solito è un collegamento simbolico a graphical.target (per desktop) o multi-user.target (per server).
  • graphical.target: Questo target è tipicamente usato per sistemi con un ambiente desktop grafico. Richiama multi-user.target e poi aggiunge i servizi necessari per il gestore di login grafico e il server di visualizzazione (ad esempio, GDM, LightDM, Xorg, Wayland).
  • multi-user.target: Questo è lo stato standard per sistemi multi-utente senza interfaccia grafica. È comune per i server e fornisce tutti i servizi necessari per l'accesso da riga di comando, la rete e la maggior parte delle operazioni dei demone.
  • basic.target: Uno stato minimale che include i servizi di sistema di base necessari per le operazioni fondamentali, ma prima di multi-user.target. Tipicamente richiama sysinit.target e altri servizi essenziali.
  • sysinit.target: Questo target viene raggiunto molto presto nel processo di avvio. È responsabile delle attività di inizializzazione del sistema di base come il montaggio dei filesystem di /etc/fstab (esclusi quelli remoti), la configurazione dello swap e altre inizializzazioni relative all'hardware.
  • local-fs.target: Assicura che tutti i filesystem locali specificati in /etc/fstab siano montati.
  • remote-fs.target: Assicura che tutti i filesystem remoti (ad esempio, NFS, CIFS) specificati in /etc/fstab siano montati.
  • network.target: Indica che la connettività di rete di base è disponibile (ad esempio, le interfacce di rete sono attive). Non garantisce la piena connettività Internet o l'assegnazione dell'indirizzo IP.
  • network-online.target: Un punto di sincronizzazione per i servizi che vogliono attendere fino a quando il gestore di rete considera la rete online. Non prova che Internet, DNS o un'API remota siano raggiungibili, e funziona come previsto solo quando il relativo servizio wait-online è abilitato.
  • rescue.target: Fornisce una shell per singolo utente con servizi minimi in esecuzione e filesystem locali montati. Utile per il recupero del sistema e la risoluzione dei problemi.
  • emergency.target: Un ambiente ancora più minimale di rescue.target. Fornisce una shell sul filesystem di root, che è tipicamente montato in sola lettura. Nessun altro servizio viene avviato. Per situazioni di emergenza critiche.
  • poweroff.target, reboot.target, halt.target: Questi target sono usati rispettivamente per spegnere, riavviare o arrestare il sistema. Quando attivati, fermano la maggior parte dei servizi e preparano il sistema per lo stato di alimentazione desiderato.

Gestione dei Target di Systemd

Interagire con i target di systemd coinvolge principalmente l'utilità da riga di comando systemctl.

Visualizzare i Target Attivi e Predefiniti

Per vedere in quale target il tuo sistema è attualmente in esecuzione:

systemctl get-default

Per elencare tutte le unità target attualmente caricate:

systemctl list-units --type=target

Questo comando mostra i target attivi, caricati e statici, insieme alle loro descrizioni.

Cambiare il Target di Avvio Predefinito

Puoi cambiare il target in cui il sistema si avvia per impostazione predefinita. Ad esempio, per impostare multi-user.target come predefinito:

sudo systemctl set-default multi-user.target

Per tornare a graphical.target:

sudo systemctl set-default graphical.target

Questo comando crea un collegamento simbolico da /etc/systemd/system/default.target al file target desiderato.

Avviare Temporaneamente in un Target Diverso

A volte è necessario avviare in un target specifico solo una volta (ad esempio, per la risoluzione dei problemi). Puoi ottenere questo aggiungendo un parametro del kernel durante l'avvio. Quando appare il menu di avvio GRUB, modifica la voce di avvio (di solito premendo e) e aggiungi systemd.unit=nome_target.target alla riga di comando del kernel.

Ad esempio, per avviare in modalità di ripristino:

systemd.unit=rescue.target

Cambiare Target Durante l'Esecuzione

Puoi passare a un target diverso mentre il sistema è in esecuzione usando il comando systemctl isolate. Questo comando fermerà tutti i servizi non richiesti dal nuovo target e avvierà tutti i servizi richiesti da esso.

Attenzione: Usare systemctl isolate può interrompere il funzionamento del sistema, specialmente se passi a un target di livello molto più basso come multi-user.target da graphical.target su una macchina desktop. Usa con cautela.

Per passare da graphical.target a multi-user.target:

sudo systemctl isolate multi-user.target

Per tornare a graphical.target (supponendo che fosse lo stato precedente):

sudo systemctl isolate graphical.target

Creare Target Personalizzati

Mentre systemd fornisce molti target utili, potresti trovare situazioni in cui creare un target personalizzato è vantaggioso. Questo è particolarmente vero per distribuzioni di applicazioni complesse dove devi raggruppare diversi servizi che dovrebbero sempre avviarsi e fermarsi insieme, o per definire un ambiente specifico per la tua applicazione.

Per creare un target personalizzato:

  1. Crea un file .target: Posizionalo in /etc/systemd/system/. Ad esempio, my-application.target.
    # /etc/systemd/system/my-application.target
    [Unit]
    Description=Target Applicazione Personalizzata
    Wants=my-database.service my-webserver.service
    After=my-database.service my-webserver.service
    
    • Description: Una descrizione leggibile dall'uomo.
    • Wants=: Elenca i servizi o altri target che questo target dovrebbe richiamare.
    • After=: Definisce l'ordine. Il target si avvierà dopo queste unità.
  2. Crea i servizi: Assicurati che my-database.service e my-webserver.service (o qualsiasi servizio elenchi) esistano e siano configurati correttamente.
  3. Ricarica systemd: Informa systemd del nuovo file unit.
    
    

sudo systemctl daemon-reload 4. **Abilita e Avvia**: Ora puoi abilitare e avviare il tuo target personalizzato, che a sua volta avvierà i servizi desiderati. bash sudo systemctl enable my-application.target sudo systemctl start my-application.target ```

Questo ti permette di gestire un gruppo di servizi correlati come una singola unità logica, semplificando distribuzioni di applicazioni complesse.

Runlevel e Target Senza Giri di Parole

Se provieni da SysVinit, la mappatura approssimativa è:

Vecchia idea di runlevel Target systemd comune
Modalità di riparazione singolo utente rescue.target
Modalità testo multi-utente multi-user.target
Modalità grafica multi-utente graphical.target
Riavvio reboot.target
Spegnimento poweroff.target

Trattalo come un aiuto alla traduzione, non un modello perfetto. I runlevel SysV erano un piccolo insieme fisso di stati numerati. I target di systemd sono unità nominate con dipendenze, e possono essercene molti. Un pacchetto può installare il proprio target. Puoi crearne uno per un flusso di lavoro di distribuzione. Alcuni target sono destinati ad essere isolati; altri sono solo punti di raggruppamento usati durante l'avvio.

Puoi vedere quali target permettono l'isolamento con:

systemctl show multi-user.target -p AllowIsolate
systemctl show basic.target -p AllowIsolate

Questo è importante perché systemctl isolate non è un comando "cambia vista" innocuo. Ferma le unità che non fanno parte della transazione del nuovo target. Su un desktop, isolare multi-user.target di solito fermerà la sessione grafica. Su un server remoto, isolare il target sbagliato può fermare i servizi di rete o di login e bloccarti fuori.

Come i Servizi Diventano Parte di un Target

La maggior parte dell'appartenenza ai target nella vita quotidiana proviene dalla sezione [Install] di un file di servizio:

[Install]
WantedBy=multi-user.target

Quando esegui:

sudo systemctl enable myapp.service

systemd crea un collegamento simbolico sotto una directory come:

/etc/systemd/system/multi-user.target.wants/myapp.service

Quel collegamento simbolico è ciò che fa sì che multi-user.target voglia il servizio durante l'avvio. Il file di servizio può esistere ed essere perfettamente valido senza essere abilitato. In tal caso, avviare multi-user.target non lo richiamerà automaticamente.

Questo è il motivo per cui systemctl start myapp.service e systemctl enable myapp.service risolvono problemi diversi. start lo esegue ora. enable lo collega a un target di avvio futuro. enable --now fa entrambe le cose.

Per verificare se un servizio è abilitato per un target:

systemctl is-enabled myapp.service
systemctl list-dependencies multi-user.target | grep myapp

Se un servizio si avvia manualmente ma non all'avvio, questa è una delle prime cose da controllare.

Un Piccolo Target Personalizzato Che È Effettivamente Utile

I target personalizzati sono più utili quando danno agli operatori un comando per un gruppo di unità correlate. Immagina un semplice stack applicativo:

app-api.service
app-worker.service
app-scheduler.service

Puoi creare:

# /etc/systemd/system/app-stack.target
[Unit]
Description=Stack applicativo
Wants=app-api.service app-worker.service app-scheduler.service
After=network-online.target
Wants=network-online.target
AllowIsolate=no

Poi aggiungi ogni servizio al target:

[Install]
WantedBy=app-stack.target

Dopo daemon-reload, abilita i servizi o il target a seconda del comportamento desiderato:

sudo systemctl daemon-reload
sudo systemctl enable app-api.service app-worker.service app-scheduler.service
sudo systemctl start app-stack.target

Questo ti dà un raggruppamento leggibile senza fingere che il target sia un supervisore di processo. Se app-worker.service fallisce, ispeziona quel servizio. Il target è solo il punto di raggruppamento.

Se vuoi che fermare il target fermi tutti i servizi dello stack, aggiungi PartOf=app-stack.target a ogni servizio:

[Unit]
PartOf=app-stack.target

Ora systemctl stop app-stack.target si propaga ai servizi membri. Questo è spesso il pezzo mancante negli esempi di target personalizzati.

Risoluzione dei Problemi con i Target

I target sono anche preziosi per risolvere problemi di avvio o guasti dei servizi:

  • Identificare le dipendenze: Se un servizio non riesce ad avviarsi, ispezionare il target a cui appartiene può rivelare dipendenze mancanti o fallite. Usa systemctl status <nome_servizio> e systemctl list-dependencies <nome_target>.
  • Avviare in target minimi: Se il tuo sistema non riesce ad avviarsi in graphical.target o multi-user.target, prova ad avviare in rescue.target o emergency.target usando il metodo del parametro del kernel. Questo fornisce un ambiente minimale dove puoi diagnosticare i problemi senza la complessità di molti servizi in esecuzione.
  • Controllare i log: Dopo aver tentato di avviare un target o un servizio, controlla sempre i log di journalctl per errori:
    journalctl -b -u <nome_target_o_servizio>
    

Migliori Pratiche e Suggerimenti

  • Usa network-online.target con attenzione: Se il tuo servizio ha bisogno della configurazione di rete prima dell'avvio, combina After=network-online.target con Wants=network-online.target e conferma che l'appropriata unità wait-online sia abilitata. Mantieni comunque la logica di ripetizione nell'applicazione per le dipendenze remote.
  • Comprendi l'ordine di avvio: Familiarizza con il flusso generale da sysinit.target a basic.target, poi multi-user.target/graphical.target. Questo aiuta nel debug dei servizi che falliscono all'inizio del processo di avvio.
  • Sii cauto con default.target: Cambiare default.target può alterare significativamente il comportamento di avvio del sistema. Testa sempre le configurazioni personalizzate in un ambiente non di produzione prima.
  • Usa Wants= per dipendenze non critiche: Per servizi che sono utili ma non strettamente necessari affinché un target sia considerato "su", usa Wants= invece di Requires=. Questo impedisce che un singolo guasto di un servizio opzionale si propaghi e impedisca l'attivazione dell'intero target.

Il Modello Mentale da Tenere

Un target è uno stato nominato, non un demone. default.target decide la destinazione normale di avvio. multi-user.target è lo stato usuale del server. graphical.target aggiunge lo stack di visualizzazione. rescue.target e emergency.target sono strumenti di riparazione. I target personalizzati sono strumenti di raggruppamento quando rendono le operazioni più chiare.

Quando qualcosa relativo a un target si rompe, evita di incolpare prima il target. Chiedi quale unità è stata richiamata, quale regola di ordinamento l'ha ritardata e quale dipendenza è fallita. systemctl cat, systemctl list-dependencies, systemctl show e journalctl -b di solito risponderanno a queste domande più velocemente che leggere diagrammi di avvio generici.