Quando GNU/Linux viene avviato, il kernel si prende cura di avviare il processo init
, a partire dal quale vengono poi generati tutti gli altri. Di solito si utilizza un meccanismo di inizializzazione derivato dallo UNIX System V.
init
determina quali siano i processi da avviare successivamente, in base al contenuto di /etc/inittab
il quale a sua volta fa riferimento a una serie di script contenuti normalmente all'interno della directory /etc/rc.d/
o in un'altra analoga.
All'interno di /etc/inittab
si distinguono azioni diverse in funzione del livello di esecuzione, di solito un numero da 0 a 6. Per convenzione, il livello 0 identifica le azioni necessarie per fermare l'attività del sistema, in modo da permetterne lo spegnimento; il livello 6 riavvia il sistema; il livello 1 mette il sistema in condizione di funzionare in modalità monoutente.
Le distribuzioni GNU/Linux più sofisticate e confortevoli permettono di configurare il sistema attraverso dei programmi che guidano l'utente. Ciò significa che questi programmi sono in grado di produrre automaticamente script e file di configurazione tradizionali, ma per fare questo devono gestire un proprio sistema di file di configurazione che non appartiene allo standard generale. |
L'organizzazione della procedura di inizializzazione del sistema e dei livelli di esecuzione costituisce il punto su cui si distinguono maggiormente le distribuzioni GNU/Linux. Benché alla fine si tratti sempre della stessa cosa, il modo di strutturare e di collocare gli script è molto diverso da una distribuzione all'altra. Quando si acquista più esperienza, ci si accorge che queste differenze non sono poi un grosso problema, ma all'inizio è importante comprendere e accettare che ciò che si usa (la propria distribuzione GNU/Linux) mostra un'interpretazione della soluzione del problema, non il risultato accettato generalmente. |
Nel capitolo 186 viene descritto in modo più dettagliato come è organizzata questa procedura nella distribuzione RedHat.
init
è il processo principale che genera tutti gli altri. All'avvio del sistema legge il file /etc/inittab
il quale contiene le informazioni per attivare gli altri processi necessari, compresa la gestione dei terminali. Per prima cosa viene determinato il livello di esecuzione iniziale (run level), ottenendo l'informazione dalla direttiva initdefault
di /etc/inittab
. Quindi vengono attivati i processi essenziali al funzionamento del sistema e infine i processi che combaciano con il livello di esecuzione attivato.
init [<opzioni>] |
Durante il funzionamento del sistema, init
può essere invocato per cambiare il livello di esecuzione.
|
Stabilisce il numero di secondi di attesa prima di cambiare il livello di esecuzione. In mancanza si intende 20 secondi.
0 | 1 | 2 | 3 | 4 | 5 | 6 |
Un numero da 0 a 6 stabilisce il livello di esecuzione.
a | b | c |
Una lettera a
, b
o c
indica a init
di eseguire soltanto i processi indicati all'interno di /etc/inittab
che hanno un livello di esecuzione pari alla lettera specificata. In pratica, una lettera non indica un livello di esecuzione vero e proprio; si tratta di una possibilità di configurazione del file /etc/inittab
per definire i cosiddetti livelli «a richiesta» (on demand).
Q | q |
Indica a init
di riesaminare il file /etc/inittab
.
S | s |
Indica a init
di passare alla modalità monoutente (single user), ma non è pensato per essere utilizzato direttamente.
#
init 1
Pone il sistema al livello di esecuzione 1: monoutente.
#
init 0
Pone il sistema al livello di esecuzione 0: system halt. Equivale (in linea di massima) all'esecuzione di shutdown
.
-
h now
#
init 6
Pone il sistema al livello di esecuzione 6: riavvio. Equivale (in linea di massima) all'esecuzione di shutdown
.
-
r now
Il file inittab
descrive quali processi vengono avviati al momento dell'avvio del sistema e durante il funzionamento normale di questo. init
, il processo principale, distingue diversi livelli di esecuzione (run level), per ognuno dei quali può essere stabilito un gruppo diverso di processi da avviare.
La struttura dei record che compongono le direttive di questo file può essere schematizzata nel modo seguente:
<id>:<livelli-di-esecuzione>:<azione>:<processo> |
<id> -- è una sequenza unica di due caratteri che identifica il record (la riga) all'interno di | |
<livelli-di-esecuzione> -- elenca i livelli di esecuzione con cui l'azione indicata deve essere eseguita; | |
<azione> -- indica l'azione da eseguire; | |
<processo> specifica il processo da eseguire. |
Se il nome del processo inizia con un simbolo +
, init
non eseguirà l'aggiornamento di /var/run/utmp
e /var/log/wtmp
per quel processo; ciò è utile quando il processo stesso provvede da solo a questa operazione.
Il penultimo campo identifica l'azione da compiere. Questa viene rappresentata attraverso una parola chiave.
Quando il processo termina, viene riavviato. | |
Il processo viene avviato una volta (sempre che il livello di esecuzione lo consenta) e | |
Il processo viene eseguito una volta quando il livello di esecuzione lo consente. | |
Il processo viene eseguito al momento dell'avvio del sistema. Il campo del livello di esecuzione viene ignorato. | |
Il processo viene eseguito al momento dell'avvio del sistema e | |
Non fa alcunché. | |
Si tratta dei record «a richiesta» che vengono presi in considerazione quando viene eseguito | |
Permette di definire il livello di esecuzione predefinito per l'avvio del sistema. Se non viene specificato, | |
Il processo viene eseguito al momento dell'avvio del sistema, prima di quelli indicati come | |
Il processo viene eseguito quando | |
Il processo viene eseguito quando | |
Il processo viene eseguito quando | |
Il processo viene eseguito quando | |
Il processo viene eseguito quando |
Il campo dei livelli di esecuzione può contenere diversi caratteri che stanno a indicare diversi possibili livelli di esecuzione. Per esempio, 123
indica che il processo specificato verrà eseguito indifferentemente per tutti i livelli di esecuzione da 1 a 3. Questo campo può contenere anche una lettera dell'alfabeto: a
, b
o c
che sta a indicare un livello on demand. Nel caso di azioni del tipo sysinit
, boot
e bootwait
, il campo del livello di esecuzione viene ignorato.
Negli esempi seguenti, si mostra prima un record del file /etc/inittab
e quindi, sotto, la sua descrizione.
id:5:initdefault: |
Definisce il livello di esecuzione iniziale: 5.
si::sysinit:/etc/rc.d/rc.sysinit |
Inizializzazione del sistema: è la prima cosa a essere eseguita dopo l'avvio del sistema stesso. In pratica viene avviato lo script /etc/rc.d/rc.sysinit
(RedHat).
l1:1:wait:/etc/rc.d/rc 1 |
Indica di eseguire /etc/rc.d/rc
, con l'argomento 1
, nel caso in cui il livello di esecuzione sia pari a 1: singolo utente (RedHat)
rc:123456:wait:/etc/rc.d/rc.M |
Indica lo script (/etc/rc.d/rc.M
) da eseguire per tutti i livelli di esecuzione da 1 a 6 (Slackware).
ca::ctrlaltdel:/sbin/shutdown -t5 -rfn now |
Indica il programma da eseguire in caso di pressione della combinazione [Ctrl+Alt+Canc]. Il livello di esecuzione non viene indicato perché è indifferente (Slackware).
l0:0:wait:/etc/rc.d/rc 0 |
Indica di eseguire /etc/rc.d/rc
, con l'argomento 0
, nel caso in cui il livello di esecuzione sia pari a 0: system halt (RedHat).
l6:6:wait:/etc/rc.d/rc 6 |
Indica di eseguire /etc/rc.d/rc
, con l'argomento 6
, nel caso in cui il livello di esecuzione sia pari a 6: riavvio (RedHat).
pf::powerfail:/sbin/shutdown -f +5 "THE POWER IS FAILING" |
Indica il programma da eseguire quando si verifica un problema con l'alimentazione elettrica (Slackware).
pg:0123456:powerokwait:/sbin/shutdown -c "THE POWER IS BACK" |
Indica il programma da eseguire se l'alimentazione elettrica torna normale prima del completamento del processo avviato quando si era verificato il problema (Slackware).
1:12345:respawn:/sbin/mingetty tty1 2:2345:respawn:/sbin/mingetty tty2 3:2345:respawn:/sbin/mingetty tty3 4:2345:respawn:/sbin/mingetty tty4 5:2345:respawn:/sbin/mingetty tty5 6:2345:respawn:/sbin/mingetty tty6 |
Si tratta dell'elenco di console virtuali utilizzabili. La prima si attiva per tutti i livelli di esecuzione da 1 a 5, le altre solo per i livelli superiori a 1. In questo caso è mingetty
a essere responsabile dell'attivazione delle console virtuali (RedHat).
s1:45:respawn:/sbin/agetty 19200 ttyS0 vt100 |
Indica l'attivazione di un terminale connesso sulla prima porta seriale. Si attiva solo con i livelli di esecuzione 4 o 5 (Slackware).
d2:45:respawn:/sbin/agetty -mt60 38400,19200,9600,2400,1200 ttyS1 vt100 |
Indica l'attivazione di un terminale remoto connesso via modem sulla seconda porta seriale. Si attiva solo con i livelli di esecuzione 4 o 5 (Slackware).
x:5:respawn:/usr/bin/X11/xdm -nodaemon |
Nel caso il livello di esecuzione sia pari a 5, esegue /usr/bin/X11/xdm
che si occupa di avviare un login all'interno dell'ambiente grafico X (RedHat).
/etc/initscript <id> <livello-di-esecuzione> <azione> <processo> |
Quando lo script di shell /etc/initscript
esiste, viene utilizzato da init
per avviare i processi indicati all'interno del file /etc/inittab
.
Di solito questo script non è presente, tuttavia potrebbe essere utile per definire delle variabili di ambiente e altre impostazioni che riguardano l'interpretazione degli script della procedura di inizializzazione del sistema. La documentazione initscript(5) mostra un esempio simile a quello seguente, che dovrebbe chiarire il senso di questa possibilità.
# initscript Executed by init(8) for every program it # wants to spawn like this: # # /bin/sh /etc/initscript <id> <level> <action> <process> # # Set umask to safe level, and enable core dumps. umask 022 PATH=/bin:/sbin:/usr/bin:/usr/sbin export PATH # Execute the program. eval exec "$4" |
Come si vede anche dai commenti dell'esempio, initscript
riceve da init
, attraverso gli argomenti, tutti i campi contenuti nel record corrispondente di /etc/inittab
.
La prima differenza importante che distingue le varie distribuzioni GNU/Linux sta nell'organizzazione degli script della procedura di inizializzazione del sistema. Il punto di riferimento comune è init
con il suo /etc/inittab
, dal quale si intende quali siano il comandi avviati in presenza di un determinato livello di esecuzione; quello che c'è dopo costituisce il problema più grosso.
Volendo semplificare molto le cose, si può pensare al fatto che ci dovrebbe essere una directory specifica, contenente un gruppetto di script utilizzato esclusivamente per questi scopi. Volendo fare un esempio preciso, nel caso della distribuzione RedHat, tale directory è /etc/rc.d/
; dagli esempi visti riguardo al file /etc/inittab
, si può notare che all'interno di questa directory si trovano gli script rc.sysinit
e rc
.
Per una convenzione diffusa, lo script rc.local
che dovrebbe essere contenuto in questa directory (/etc/rc.d/
, o altra directory a seconda della propria distribuzione GNU/Linux), viene eseguito alla fine della procedura di inizializzazione del sistema, e viene lasciato a disposizione dell'amministratore che può modificarlo come crede. Volendo fare un'associazione con il sistema Dos, si potrebbe paragonare questo script al file AUTOEXEC.BAT
.
Le motivazioni che spingono a un'impostazione differente di questi script della procedura di inizializzazione del sistema, possono essere varie. Anche la collocazione di tale directory è controversa, a cominciare dal fatto che la directory /etc/
non dovrebbe contenere programmi e nemmeno script. Infatti, a questo proposito, la distribuzione SuSE colloca questi script nella directory /sbin/init.d/
.
Il sistema di script della procedura di inizializzazione del sistema ha il compito di avviare il sistema e di fermarlo, attivando e disattivando tutti i servizi necessari, cioè intervenendo nell'avvio e nella conclusione del funzionamento dei demoni relativi.
Si può intuire che non sia possibile realizzare uno o più script del genere per avviare tutti i tipi di demone che possono essere presenti nel proprio sistema, anche perché ci possono essere dei servizi installati che però non si vogliono gestire. Di conseguenza, nella situazione più banale, quando si intende installare e gestire un nuovo servizio, occorre anche modificare la procedura di inizializzazione del sistema per attivare il demone relativo e per disattivarlo nel momento dell'arresto del sistema. Una cosa del genere può andare bene per una persona esperta, ma si tratta sempre di un'impostazione piuttosto scomoda.
Nel tempo si è diffuso uno standard per risolvere questo problema, ed è ciò che viene descritto nelle sezioni seguenti.
Secondo una convenzione diffusa, per facilitare l'avvio e la conclusione dei servizi si definisce una directory specifica, che potrebbe essere /etc/rc.d/init.d/
, o /etc/init.d/
, o ancora /sbin/init.d/
, all'interno della quale si possono inserire degli script che hanno una sintassi uniforme.
<nome-servizio> {start|stop} |
In pratica, il nome dello script tende a corrispondere a quello del servizio che si intende controllare; l'argomento costituito dalla parola chiave start
fa sì che lo script avvii il servizio, mentre la parola chiave stop
serve a concluderlo.
Questi script possono essere più o meno raffinati, per esempio possono accettare anche altri tipi di ordini (come restart
, allo scopo di riavviare un servizio), ma la cosa più importante è che dovrebbero evitare di avviare dei doppioni, controllando prima di avviare qualcosa, se per caso questo risulta già attivo. Naturalmente, un servizio può essere ottenuto con l'avvio di diversi programmi demone, e in questo è molto comodo tale sistema di script specifici.
A titolo di esempio viene mostrato come potrebbe essere composto uno script del genere, per l'avvio del servizio ipotetico denominato pippo
, che si avvale del programma omonimo per gestirlo. Per semplicità, non vengono indicati accorgimenti particolari per controllare che il servizio sia già attivo o meno.
#!/bin/sh # # init.d/pippo {start|stop|restart} # # Analisi dell'argomento usato nella chiamata. case "$1" in start) echo -n "Avvio del servizio Pippo: " /usr/sbin/pippo & echo ;; stop) echo -n "Disattivazione del servizio Pippo: " killall pippo echo ;; restart) killall -HUP pippo ;; *) echo "Utilizzo: pippo {start|stop|restart}" exit 1 esac exit 0 |
Lo scopo e la vera utilità di questi script sta nel facilitare una standardizzazione della procedura di inizializzazione del sistema; tuttavia si può intuire la possibilità di sfruttarli anche per attivare e disattivare manualmente un servizio, senza intervenire direttamente sui programmi relativi.
Procedendo intuitivamente, si potrebbe pensare di fare in modo che la procedura di inizializzazione del sistema, all'avvio, provveda a eseguire tutti gli script di controllo dei servizi, utilizzando l'argomento start
, e allo spegnimento, provveda a eseguirli con l'argomento stop
. Una cosa del genere è molto semplice da realizzare, ma si pongono due problemi: alcuni servizi potrebbero essere a disposizione, senza che la procedura di inizializzazione del sistema debba avviarli automaticamente; la sequenza di attivazione e di disattivazione dei servizi potrebbe essere importante.
In pratica, si utilizza un meccanismo molto semplice: si predispongono tante directory quanti sono i livelli di esecuzione gestiti attraverso il file /etc/inittab
. Queste directory hanno il nome rc
n.d/
, dove n rappresenta il numero del livello di esecuzione corrispondente. La loro collocazione effettiva potrebbe essere /etc/rc
n.d/
, /etc/rc.d/rc
n.d/
o anche /sbin/init.d/rc
n.d/
. All'interno di queste directory si inseriscono dei collegamenti simbolici che puntano agli script descritti nella sezione precedente, in modo che siano presenti i riferimenti ai servizi desiderati per ogni livello di esecuzione (distinto in base alla directory rc
n.d/
particolare).
I nomi di questi collegamenti iniziano in modo speciale: K
nn... e S
nn... I collegamenti che iniziano con la lettera «S» (Start) servono per individuare gli script da utilizzare per l'attivazione dei servizi, vengono avviati con l'argomento start
, in ordine alfabetico, e a questo servono le due cifre numeriche successive: a distinguerne la sequenza. I collegamenti che iniziano con la lettera «K» (Kill) servono per individuare gli script da utilizzare per la disattivazione dei servizi, vengono avviati con l'argomento stop
, anche questi in ordine alfabetico.
Ecco, a titolo di esempio, cosa potrebbe contenere una di queste directory.
lrwxrwxrwx 1 root root 13 13:39 K15gpm -> ../init.d/gpm lrwxrwxrwx 1 root root 13 13:39 K60atd -> ../init.d/atd lrwxrwxrwx 1 root root 15 13:39 K60crond -> ../init.d/crond lrwxrwxrwx 1 root root 16 13:39 K96pcmcia -> ../init.d/pcmcia lrwxrwxrwx 1 root root 17 13:39 S01kerneld -> ../init.d/kerneld lrwxrwxrwx 1 root root 17 13:39 S10network -> ../init.d/network lrwxrwxrwx 1 root root 15 13:39 S15nfsfs -> ../init.d/nfsfs lrwxrwxrwx 1 root root 16 13:39 S20random -> ../init.d/random lrwxrwxrwx 1 root root 16 13:39 S30syslog -> ../init.d/syslog lrwxrwxrwx 1 root root 14 13:39 S50inet -> ../init.d/inet lrwxrwxrwx 1 root root 18 13:39 S75keytable -> ../init.d/keytable |
Osservando i servizi syslog
e inet
, si può notare il numero attribuito per l'avvio, che serve a fare in modo che il servizio syslog
sia avviato prima di inet
.
Sempre a titolo di esempio, viene mostrato un pezzo di uno script, per una shell Bourne o derivata, fatto per scandire un elenco di collegamenti del genere, allo scopo di attivare e di disattivare i servizi, a partire dai collegamenti contenuti nella directory /etc/rc.d/rc3.d/
. Per un lettore inesperto, questo potrebbe essere un po' difficile da leggere, ma l'esempio viene aggiunto per completare l'argomento.
#!/bin/sh #... # Attivazione dei servizi del livello di esecuzione 3. for I in /etc/rc.d/rc3.d/K*; do # Disattiva il servizio. $I stop done for I in /etc/rc.d/rc3.d/S*; do # Attiva il servizio. $I start done |
In pratica, prima si disattivano i servizi corrispondenti ai collegamenti che iniziano con la lettera «K», quindi si attivano quelli che hanno la lettera «S». Si può intuire che le directory rc0.d/
e rc6.d/
contengano prevalentemente, o esclusivamente, riferimenti che iniziano con la lettera «K», dal momento che i livelli di esecuzione corrispondenti portano all'arresto del sistema o al suo riavvio.
---------------------------
Appunti Linux 1999.07.12 --- Copyright © 1997-1999 Daniele Giacomini -- daniele @ evo.it
[indice generale] [precedente] [successivo] [indice analitico] [note introduttive]