Gentoo Linux 1.0 Init System
1.Introduzione
Gentoo Linux usa un sistema di inizializzazione (init system) che è
controllato attraverso dipendenze. Dovrebbe essere semplice da mantenere
oltre che abbastanza potente e flessibile per ogni tipo
di setup.
Questa guida non deve essere considerata una introduzione su come
funziona il sistema internamente, ma come una rapida guida su come
I più curiosi sono invitati a leggersi i sorgenti.
2.Runlevel
A differenza di altri init system, Gentoo non ha rigidi nomi
o numeri per definire i runlevel, ma piuttosto nomi comuni mappati
nello standard runlevel di init.
Nota:
Per default ci sono tre runlevel, chiamati "boot",
"default"
e "nonetwork".
|
Il runlevel "boot" dovrebbe essere lo standard per
molti setup e, come denota il nome, è il primo runlevel ad
essere eseguito dopo il boot time. Quindi c'è
il "default" che, come indica il nome, è
il principale runlevel ad essere eseguito dopo il boot.
L'ultimo è "nonetwork" che serve puramente
come esempio.
I runlevel sono collocati in /etc/runlevels, in
sottodirectory chiamate con i nomi dei runlevel dentro
le quali si trovano dei link ai servizi che sono propri del
runlevel corrispondente.
Nota:
Il modo migliore per aggiungere o rimuovere servizi
sarà discusso nella sezione "L'utilità
rc-update".
|
Come abbiamo già detto, il nome avrebbe potuto essere cambiato a seconda
delle necessità dell'utente, e come regola dovrebbe essere cambiato
anche il file /etc/inittab per riflettere il nuovo
nome del runlevel di default.
Importante: Un eccezione alla regola riguarda il runlevel "boot"
|
Attenzione:
NON cambiate il nome del runlevel "boot"
perché potrebbe non funzionare più niente.
|
Tutto il lavoro è svolto dallo script /sbin/rc
che può anche essere usato per cambiare il runlevel al volo.
Runlevel virtuali
Dato che i runlevel non sono staticamente mappati a quelli di init,
ci possono essere più livelli rispetto a quelli
supportati da init. Questo permette all'utente di creare
profili o runlevel virtuali a seconda del bisogno.
Per esempio, su un lapotop possiamo avere due runlevel
di default, chiamati "online" e "offline".
Questo ci permetterebbe di avere un runlevel quando la scheda
di rete PCMCIA è attiva ed uno quando non lo è.
Lo scripts PCMCIA potrebbe essere configurato in modo da chiamare
"/sbin/rc online" o
"/sbin/rc offline" in modo da far partire o
fermare i corretti servizi a seconda dello stato della scheda
di rete PCMCIA.
Runlevel e XFree86
In Gentoo non abbiamo un runlevel dedicato a X, ma piuttosto
uno script di startup il quale è chiamato "xdm"
e può essere aggiunto a qualsiasi runlevel che vogliamo.
Nota:
In effetti dovrebbe essere messo nel runlevel
principale che desiderate.
|
Attenzione:
Aggiungendolo al runlevel di boot i risultati
possono essere imprevedibili.
|
Di default se avete fatto partire xdm, gdm o kdm dopo la
partenza delle getty, X probabilmente partirà
nella prossima console disponibile. Su macchine lente non
è un problema se il Desktop Manager parte verso la fine
dei processi iniziali del runlevel.
Le getty partiranno prima di X che partirà nella console 7
come dovrebbe.
Su macchine veloci comunque questo non è così. X parte
prima delle getty e quindi nella console 2, Quando getty parte
prende il controllo della tastiera e il Desktop Manager perde il
supporto della tastiera.
Per ovviare a questo problema lo script di startup del Desktop
Manager viene posto in un'extra init runlevel chiamato runlevel 'a'.
Quest'ultimo non è un runlevel reale, il nostro script
"xdm" richiamerà "telinit a"
che rischedulerà tutti i servizi in runlevel 'a' perché
siano eseguiti dopo il runlevel corrente, dopo cioè che getty
è partito.
Nota:
Maggiori informazioni circa il runlevel 'a'
possono essere acquisite leggendo le man pages
di init.
|
3.rc-script
Gli rc-script sono script che definiscono le funzioni
di base per ogni servizio, così come le sue dipendenze,
per la partenza. La directory di riferimento è
/etc/init.d/.
Come si presenta un rc-script di base
Esempio 1: rc-script layout |
#!/sbin/runscript
depend() {
need bar
}
start() {
ebegin "Starting foo"
/sbin/foo
eend $? "Failed to start foo"
}
stop() {
ebegin "Stopping foo"
kill $(cat /var/run/foo.pid)
eend $? "Failed to stop foo"
}
|
Nota:
L'interprete è "/sbin/runscript".
|
Nota:
La funzione "depend" è opzionale.
|
Nota:
Ogni rc-script ha bisogno almeno della funzione
"start".
|
Controllare l'avvio dei servizi
In genere l'ordine di avvio dei servizi è alfabetico.
Questo è causato dall'output generato da /bin/ls.
Il metodo primario per deviare dalla sequenza di avvio di default,
sono le dipendenze.
Alternativamente se non c'è relazione tra i servizi, può
essere usata la sequenza tipo.
4.Tipi di dipendenze
Molti servizi hanno relazione o sono dipendenti da altri.
Postfix, per esempio, ha bisogno che la rete sia funzionante,
così come il sistema di log.
Samba ha bisogno di una rete funzionante. Se CUPS viene
usato per stampare, cupsd dovrebbe partire prima di samba.
Cups non è comunque strettamente necessario a samba.
Abbiamo così due modi per esprimere le dipendenze che
relazionano differenti servizi.
Queste dipendenze sono sempre valide, sia che il runlevel sia
cambiato per intero, sia che il servizio sia fatto partire o sia
fermato manualmente dopo l'avvio della macchina.
Quando initscript multipli forniscono una certa virtualità (
come se avessimo script net.eth*
multipli che provvedono tutti la dipendenza "net"), solo
uno di loro sarà usato per fornire tale dipendenza.
Così se abbiamo uno script che necessita della dipendenza net
(need net),
userà uno solo degli script net.eth* disponibile e
non tutti.
La dipendenza di tipo NEED
La dipendenza di tipo NEED è usata se un servizio è
indispensabile per la corretta partenza del servizio corrente.
Esempio 2: aggiungiamo logger e net come dipendenze di tipo NEED |
depend() {
need net logger
}
|
Nota:
I servizi menzionati dopo NEED sono critici per
la partenza del servizio corrente la cui partenza
fallirà se una delle dipendenze non parte.
|
Importante:
Ogni servizio nella linea NEED sarà fatto
partire anche se NON è incluso nel corrente runlevel o
in quello di "boot".
|
NEED crea così una dipendenza molto "forte".
La dipendenza di tipo USE
La dipendenza di tipo USE è usata per quei
servizi che non sono critici per la partenza del servizio corrente,
ma che dovrebbero partire prima di tale servizio se è usato.
Esempio 3: aggiungiamo portmap come dipendenza di tipo USE a netmount |
depend() {
use portmap
}
|
Netmount può usare mount di tipo NFS, ma questo dipende
se il portmap è aggiunto al runlevel corrente o di boot.
Ogni utente con mount NFS dovrebbe per default aggiungere
portmap al runlevel di default, in modo tale che netmount veda
portmap come una dipendenza USE e lo faccia partire prima di se stesso.
Importante:
Ogni servizio nella linea USE *deve* essere aggiunto al
runlevel corrente o a quello di boot per essere considerato
una dipendenza valida USE.
|
USE è così una dipendenza "debole".
Nota:
Se ogni servizio in una linea USE non parte, il servizio
corrente partirà lo stesso, come se i servizi nella linea
USE non fossero critici per l'avvio del servizio corrente.
|
5.Controllare la sequenza di avvio senza dipendenze
Se non esistono relazioni di dipendenza tra due servizi,
ma è necessario o si desidera far partire esplicitamente
un servizio dopo un altro, possono essere usate le relazioni
AFTER e BEFORE.
Nota:
Questi due tipi sono validi solo durante un cambio
di runlevel.
|
Opzionalmente è supportato il carattere "*" per
includere altri servizi:
Esempio 4: un esempio di AFTER col carattere * |
depend() {
after *
}
|
Questo causerà la partenza del servizio corrente *dopo*
tutti gli altri servizi.
La relazione di tipo BEFORE
Il servizio corrente partirà *prima* di tutti quelli elencati
nella linea BEFORE.
Esempio 5: il corrente servizio parte prima di bar |
depend() {
before bar
}
|
La relazione di tipo AFTER
Il servizio corrente parte *dopo* tutti quelli
elencati nella linea AFTER.
Esempio 6: il corrente servizio parte dopo foo |
depend() {
after foo
}
|
6.Servizi virtuali
I servizi, come molte cose nell'odierno mondo unix, sono di molti tipi e generi.
Di solito è la scelta dell'utente/amministratore a determinare
quelli che saranno usati.
I sistemi di log ne sono un esempio. Al momento della scrittura di
questo manuale, Gentoo Linux permette di scegliere fra quattro
differenti sistemi di log.
Tutti i servizi che necessitano che un sistema di log sia in uso prima
di partire, non possono aver bisogno di tutti e quattro,
attraverso l'uso di NEED. D'altra parte includerli in
USE è controindicato data la dipendenza "debole".
E' qui dove i servizi virtuali e la dipendenza PROVIDE
entrano in gioco.
La relazione di tipo PROVIDE
La relazione di tipo PROVIDE definisce servizi virtuali di cui altri
servizi necessitano. (Servizi che possono essere in relazioni di tipo NEED
o USE).
Esempio 7: sysklogd provvede servizi di log |
depend() {
provide logger
}
|
Il servizio virtuale LOGGER
LOGGER è un servizio virtuale predefinito che è
fornito da tutti i sistemi di log e può essere usato
sia con relazioni di tipo NEED che con quelle di tipo USE.
Il servizio virtuale NET
Il servizio NET è un altro servizio virutale, ma a differenza
di LOGGER, non provvede (PROVIDE) esplicitamente un servizio.
Importante:
Per fornire un servizio virtuale NET, un servizio deve:
- essere aggiunto al runlevel corrente o di boot.
- avere un "net." seguito dall'attuale
interfaccia di rete (per esempio net.eth0 o net.ppp1).
|
Per ogni servizio valido net.*, $IFACE sarà impostata col nome dell'interfaccia
di rete. ("eth0" per net.eth0).
7.Opzioni predefinite per la linea di comando
Ogni servizio può essere chiamato con le opzioni predefinite.
Tutte quelle menzionate sono già predefinite, eccetto che per
START e STOP che l'utente dovrebbe definire
come funzioni del proprio rc-script.
Importante:
La funzione start() deve essere definita. |
Nota:
La funzione stop() è meno importante e può
essere omessa. |
Nota: In generale, l'utente dovrà solo definire start(),
stop() e restart(). Il resto è interno e dovrebbe
essere lasciato invariato. |
Esempio 8: far partire il servizio httpd |
# /etc/init.d/httpd start
|
Nota: Le opzioni sulla linea di comando possono anche essere
scritte una dopo l'altra.
|
Esempio 9: pause/start net.eth0 |
# /etc/init.d/net.eth0 pause start
|
Le opzioni START/STOP
START fa partire il servizio e quelli dai quali dipende.
STOP ferma il servizio incluso ogni servizio che dipende da lui.
L'opzione RESTART
Il servizio deve essere già attivo perché RESTART funzioni.
RESTART farà ripartire il servizio e quelli che dipendono da lui.
Importante: Se è definita una funzione restart(), l'utente
dovrebbe usare "svc_start()" e "svc_stop()"
per far partire e fermare il servizio. |
Nota: Questo per gestire correttamente tutti i servizi
dipendenti. |
L'opzione PAUSE
Questa opzione fermerà il servizio, ma a differenza di STOP,
non verrà fermato nessun servizio dipendente.
L'opzione ZAP
Inizializza lo stato del servizio che deve essere fermato.
Nota: Notate che nessuno dei comandi nella funzione stop()
sarà eseguito. L'utente dovrebbe fare ogni azione necessaria.
|
Le opzioni INEED/NEEDSME
INEED lista i servizi NEED per il corrente servizio.
NEEDSME lista i servizi per i quali questo servizio è
necessario (NEED).
Le opzioni IUSE/USESME
IUSE lista i servizi USE per il corrente servizio.
USESME lista i servizi che usano (USE) questo servizio.
L'opzione BROKEN
BROKEN lista i servizi omessi (se ce ne sono) dei quali il
corrente servizio ha bisogno (NEED).
8.Aggiungere nuove opzioni per la linea di comando
E' relativamente facile aggiungere nuove opzioni per la linea di comando.
Una funzione con una opzione ha bisogno di essere definita nell' rc-script e
aggiunta alla variabile $opts, come mostrato di eguito:
Esempio 10: foo come una nuova opzione |
opts="${opts} foo"
foo() {
............
}
|
9.Configurazione
Le configurazioni dovrebbero generalmente essere sempre definite attraverso variabili
ambiente. Queste, comunque, non dovrebbero essere definite nell' rc-script,
ma in uno dei tre possibili file di configurazione.
Uno è specifico per gli rc-script, gli altri due sono file
di configurazione globali:
Esempio 11: file di configurazione per gli rc-script |
/etc/conf.d/<nome dell' rc-script>
/etc/conf.d/basic
/etc/rc.conf
|
Nota:
Questi tre file di configurazione vengono letti automaticamente
nell'ordine che abbiamo dato.
|
Importante:
Tutti i servizi NET hanno il
loro punto di partenza in /etc/conf.d/net
|
10.Utilità per gli rc-script
L'utilità rc-update
Lo strumento primario per aggiungere e rimuovere
servizi in e da un runlevel è rc-update.
Attraverso rc-update verrà eseguito "depscan.sh" per aggiornare
la cache delle dipendenze.
Esempio 12: aggiungere metalog al runlevel di default |
# rc-update add metalog default
|
Esempio 13: rimuovere metalog dal runlevel di default |
# rc-update del metalog default
|
Nota:
L'esecuzione del comando rc-update senza argomenti
dovrebbe visualizzare maggiori informazioni.
|
Lo script depscan.sh
Per completezza, depscan.sh è menzionato qui. E' usato per
creare una cache di dipendenze che basilarmente è una mappa
delle dipendenze tra i servizi.
Dovrebbe essere eseguito ogni volta che un nuovo rc-script è
aggiunto a /etc/init.d, ma dato che viene automaticamente
eseguito da rc-update, non è necessario eseguirlo nuovamente.
|