[inizio] [indice generale] [precedente] [successivo] [indice analitico] [contributi]


27. Procedura di inizializzazione del sistema (System V)

Quando GNU/Linux viene avviato, il kernel si prende cura di avviare il processo iniziale, 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 (run level), di solito un numero da zero a sei. Per convenzione, il livello zero identifica le azioni necessarie per fermare l'attività del sistema, in modo da permetterne lo spegnimento; il livello sei riavvia il sistema; il livello uno 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, e non il risultato definitivo.

Nei capitoli 249 e 247 viene descritto in modo più dettagliato come è organizzata questa procedura nelle distribuzioni Red Hat e Debian.

27.1 Init

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, 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.

27.1.1 # init

init [<opzioni>]

L'eseguibile `init' può essere invocato dall'utente `root' durante il funzionamento del sistema, per cambiare il livello di esecuzione, oppure ottenere il riesame del suo file di configurazione (`/etc/inittab').

Opzioni

-t <secondi>

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 zero a sei stabilisce il livello di esecuzione a cui si vuole passare.

a | b | c

Una lettera `a', `b' o `c' indica a 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, in quanto si tratta di una possibilità di configurazione del file `/etc/inittab' per definire i cosiddetti livelli «a richiesta» (on demand).

Q | q

Richiede di riesaminare il file `/etc/inittab' (dopo che questo è stato modificato).

S | s

Richiede di passare alla modalità monoutente, ma non è pensato per essere utilizzato direttamente, in quanto per questo si preferisce selezionare il livello di esecuzione numero uno.

Esempi

init 1

Pone il sistema al livello di esecuzione uno: monoutente.

init 0

Pone il sistema al livello di esecuzione zero: arresto del sistema. Equivale (in linea di massima) all'esecuzione di `shutdown -h now'.

init 6

Pone il sistema al livello di esecuzione sei: riavvio. Equivale (in linea di massima) all'esecuzione di `shutdown -r now'.

27.1.2 /etc/inittab

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, 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>

  1. <id> -- è una sequenza unica di due caratteri che identifica il record (la riga) all'interno di `inittab';

  2. <livelli-di-esecuzione> -- elenca i livelli di esecuzione con cui l'azione indicata deve essere eseguita;

  3. <azione> -- indica l'azione da eseguire;

  4. <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 (la descrizione del significato e dell'importanza di questi due file si trova nel capitolo 38).

Il penultimo campo dei record di questo file, identifica l'azione da compiere. Questa viene rappresentata attraverso una parola chiave, come descritto dall'elenco seguente.

Il secondo campo, quello dei livelli di esecuzione, può contenere diversi caratteri che stanno a indicare diversi possibili livelli di esecuzione. Per esempio, la stringa `123' indica che il processo specificato verrà eseguito indifferentemente per tutti i livelli di esecuzione da uno a tre. Questo campo può contenere anche una lettera dell'alfabeto: `a', `b' o `c' che sta a indicare un livello a richiesta. Nel caso di azioni del tipo `sysinit', `boot' e `bootwait', il campo del livello di esecuzione viene ignorato.

Esempi

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: cinque.

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' (Red Hat).

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 uno: singolo utente (Red Hat)

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 uno a sei (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 zero: arresto del sistema (Red Hat).

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 sei: riavvio (Red Hat).

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 uno a cinque, le altre solo per i livelli superiori a uno. In questo caso è `mingetty' a essere responsabile dell'attivazione delle console virtuali (Red Hat).

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 quattro o cinque (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 quattro o cinque (Slackware).

x:5:respawn:/usr/bin/X11/xdm -nodaemon

Nel caso il livello di esecuzione sia pari a cinque, esegue `/usr/bin/X11/xdm' che si occupa di avviare una procedura di accesso (login) all'interno dell'ambiente grafico X (Red Hat).

27.1.3 /etc/initscript

/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 una serie di argomenti che rappresentano tutti i campi contenuti nel record corrispondente di `/etc/inittab'.

27.2 Script della procedura di inizializzazione del sistema

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 Red Hat, 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'. *1*

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/'.

27.3 Procedura di attivazione e disattivazione dei servizi

Gli script della procedura di inizializzazione del sistema hanno il compito di avviare il sistema operativo 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.

27.3.1 Script di avvio e interruzione di un servizio

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.

27.3.2 Collegamenti simbolici per ogni livello di esecuzione

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 `rcn.d/', dove n rappresenta il numero del livello di esecuzione corrispondente. La loro collocazione effettiva potrebbe essere `/etc/rcn.d/', `/etc/rc.d/rcn.d/' o anche `/sbin/init.d/rcn.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 `rcn.d/' particolare).

I nomi di questi collegamenti iniziano in modo speciale: `Knn...' e `Snn...' 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 2000.04.12 --- Copyright © 1997-2000 Daniele Giacomini --  daniele @ pluto.linux.it


1.) La distribuzione GNU/Linux Debian non prevede la presenza di questo script. Tuttavia, questo fatto non costituisce un limite, dal momento che nulla vieta di realizzarne uno analogo da collocare nella directory `/etc/init.d/', e da collegare poi nelle directory `/etc/rcn.d/'.


[inizio] [indice generale] [precedente] [successivo] [indice analitico] [contributi]