Product SiteDocumentation Site

Capitolo 9. Servizi Unix

9.1. Avvio del sistema
9.1.1. Il sistema di init systemd
9.1.2. Il sistema di init System V
9.2. Accesso remoto
9.2.1. Accesso remoto sicuro: SSH
9.2.2. Utilizzo di desktop remoti grafici
9.3. Gestione dei permessi
9.4. Interfacce di amministrazione
9.4.1. Amministrare tramite un'interfaccia Web: webmin
9.4.2. Configurazione dei pacchetti: debconf
9.5. syslog, eventi di sistema
9.5.1. Principi e meccanismi
9.5.2. Il file di configurazione
9.6. Il super-server inetd
9.7. Pianificare attività con cron e atd
9.7.1. Formato del file crontab
9.7.2. Utilizzo del comando at
9.8. Pianificazione di attività asincrone: anacron
9.9. Quote
9.10. Backup
9.10.1. Backup con rsync
9.10.2. Ripristino di macchine senza backup
9.11. Collegamento a caldo: hotplug
9.11.1. Premessa
9.11.2. Il problema dei nomi
9.11.3. Come funziona udev
9.11.4. Un esempio concreto
9.12. Gestione dell'energia: Advanced Configuration and Power Interface (ACPI)
Questo capitolo comprende una serie di servizi di base che sono comuni a molti sistemi Unix. Tutti gli amministratori dovrebbero conoscerli bene.

9.1. Avvio del sistema

Quando si avvia il computer, i molti messaggi che scorrono sulla console visualizzano molte inizializzazioni e configurazioni automatiche che vengono eseguite. Può capitare di voler modificare un po' come funziona questa fase, il che significa che è necessario conoscerla bene. Questo è lo scopo di questa sezione.
In primo luogo, il BIOS prende il controllo del computer, rileva i dischi, carica il Master Boot Record, ed esegue il bootloader. Il bootloader subentra, trova il kernel sul disco, lo carica e lo esegue. Il kernel è quindi inizializzato, e comincia a cercare e montare la partizione contenente il file system root, infine esegue il primo programma — init. Spesso, questa "partizione root" e questo init sono, di fatto, presenti in un filesystem virtuale che esiste solo nella RAM (da qui il suo nome, "initramfs", precedentemente chiamato "initrd" che sta per "disco RAM di inizializzazione"). Questo filesystem è caricato in memoria dal bootloader, spesso da un file su disco rigido o dalla rete. Contiene il minimo indispensabile richiesto dal kernel per caricare il "vero" filesystem root: possono essere moduli driver per l'hard disk, o altri dispositivi senza i quali il sistema non si avvia, o, più frequentemente, gli script di inizializzazione ed i moduli per il montaggio degli array RAID, l'apertura di partizioni cifrate, l'attivazione di volumi LVM, ecc. Una volta che la partizione di root è montata, initramfs passa il controllo all'init reale, e la macchina torna al processo di avvio standard.
Sequenza di avvio di un computer Linux con systemd

Figura 9.1. Sequenza di avvio di un computer Linux con systemd

9.1.1. Il sistema di init systemd

Il "vero init" è attualmente fornito da systemd e questa sezione documenta questo sistema di init.
Systemd esegue diversi processi, responsabili della configurazione del sistema: tastiera, drivers, filesystem, rete, servizi. Lo fa mantenendo una vsione globale del sistema nel suo complesso, ed i requisiti dei componenti. Ciascun componente è descritto da un "file unit" (a volte più); la sintassi generale deriva dalla sintassi ampiamente usata nei "file *.ini", con coppie chiave = valore raggruppate tra le intestazioni [section]. I file unit vengono memorizzati in /lib/systemd/system/ e /etc/systemd/system/; sono disponibili in vari gusti, ma qui ci si concentrerà su "service" e "target".
Un "service file" di systemd descrive un processo gestito da systemd. Contiene più o meno le stesso informazioni degli script-init vecchio stile, ma ma espresse in modo dichiarativo (e molto più conciso). systemd gestisce la maggior parte dei compiti ripetitivi (avviare e arrestare il processo, controllare il suo stato, la registrazione, far cadere i privilegi, e così via), ed il service file ha bisogno solo di compilare le specifiche dei processi. Per esempio, questo è un service file per SSH:
[Unit]
Description=OpenBSD Secure Shell server
After=network.target auditd.service
ConditionPathExists=!/etc/ssh/sshd_not_to_be_run

[Service]
EnvironmentFile=-/etc/default/ssh
ExecStart=/usr/sbin/sshd -D $SSHD_OPTS
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure

[Install]
WantedBy=multi-user.target
Alias=sshd.service
Come si può vedere, c'è poco codice lì dentro, solo dichiarazioni. Systemd si occupa di visualizzare i report, tenendo tracci dei processi, ed anche riavviandoli quando necessario.
Un "target file" di systemd descrive uno stato del sistema, dove un insieme di servizi sono noti per essere operativi. Può essere pensato come un equivalente del runlevel vecchio-stile. Uno dei target è local-fs.target; quando è raggiunto, il resto del sistema può ritenere tutti i filesystem locali montati ed accessibili. Un'altro target include network-online.target e sound.target. Le dipendenze del target possono essere elencate sia nel file di destinazione (alla riga Requires=), oppure usando un collegamento simbolico al file del servizio nella directory /lib/systemd/system/targetname.target.wants/. Per esempio, /etc/systemd/system/printer.target.wants/ contiene un collegamento a /lib/systemd/system/cups.service; systemd si assicurerà quindi che CUPS sia in esecuzione in modo da raggiungere il target printer.target.
Dal momento che gli unit file sono dichiararativi e non script o programmi, non possono essere eseguiti direttamente, e sono solo interpretati da systemd; diverese utility consentono quindi all'amministratore di interagire con systemd e controllare lo stato del sistema e di ogni componente.
La prima di queste utility è systemctl. Quando viene eseguita senza argomenti, elenca tutti gli unit file noti a systemd (eccetto quelli che sono stati disabilitati), coì come il loro stato. systemctl status dà una migliore visione dei servizi, nonchè dei relativi processi. Se viene passato il nome di un servizio (come in systemctl status ntp.service), restituisce ancora più dettagli, così come le ultime righe dei log relativi al servizio (ne parleremo più avanti).
L'avvio manuale del servizio è una cosa semplice eseguendo systemctl start nomedelservizio.service. Come si può intuire, l'arresto di un servizio è fatto con systemctl stop nomedelservizio.service; altri comandi includono reload e restart.
Per controllare se un servizio è attivo (es. se partirà automaticamente all'avvio), usa systemctl enable nomedelservizio.service (oppure disable). is-enabled permette il controllo dello stato del servizio.
Una caratteristica interessante di systemd è che include un componente di registrazione chiamato journald. Si presenta come un complemento a più sistemi di registrazione tradizionali come syslogd, ma aggiunge delle caratteristiche interessanti come un collegamento formale tra un servizio ed i messaggi che genera, e la capacità di cattuare i messaggi generati dalla sua sequenza di avvio. I messaggi possono essere visualizzati in seguito, con un piccolo aiuto da parte del comando journalctl. Senza argomenti, sputa fuori semplicemente tutti i messaggi di log che si sono verificati dall'avvio del sistema; raramente è usato in questo modo. La maggior parte delle volte sarà utilizzato con un identificatore del servizio:
# journalctl -u ssh.service
-- Logs begin at Tue 2015-03-31 10:08:49 CEST, end at Tue 2015-03-31 17:06:02 CEST. --
Mar 31 10:08:55 mirtuel sshd[430]: Server listening on 0.0.0.0 port 22.
Mar 31 10:08:55 mirtuel sshd[430]: Server listening on :: port 22.
Mar 31 10:09:00 mirtuel sshd[430]: Received SIGHUP; restarting.
Mar 31 10:09:00 mirtuel sshd[430]: Server listening on 0.0.0.0 port 22.
Mar 31 10:09:00 mirtuel sshd[430]: Server listening on :: port 22.
Mar 31 10:09:32 mirtuel sshd[1151]: Accepted password for roland from 192.168.1.129 port 53394 ssh2
Mar 31 10:09:32 mirtuel sshd[1151]: pam_unix(sshd:session): session opened for user roland by (uid=0)
Un'altro utile flag da riga di comando è -f, che indica a journalctl di mantenere la visualizzazione di nuovi messaggi quando sono emessi (più di quanto faccia tail -f file).
Se un servizio sembra non funzionare come previsto, la prima cosa da fare per risolvere il problema è quella di verifica se il servizio sia effettivamente in esecuzione con systemctl status; se non lo è, ed i messaggi dati dal primo comando non sono sufficienti a diagnosticare il problema, controllare i log raccolti da journald su quel servizio. Ad esempio, si supponga che il server SSH non funzioni:
# systemctl status ssh.service
● ssh.service - OpenBSD Secure Shell server
   Loaded: loaded (/lib/systemd/system/ssh.service; enabled)
   Active: failed (Result: start-limit) since Tue 2015-03-31 17:30:36 CEST; 1s ago
  Process: 1023 ExecReload=/bin/kill -HUP $MAINPID (code=exited, status=0/SUCCESS)
  Process: 1188 ExecStart=/usr/sbin/sshd -D $SSHD_OPTS (code=exited, status=255)
 Main PID: 1188 (code=exited, status=255)

Mar 31 17:30:36 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a
Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state.
Mar 31 17:30:36 mirtuel systemd[1]: ssh.service start request repeated too quickly, refusing to start.
Mar 31 17:30:36 mirtuel systemd[1]: Failed to start OpenBSD Secure Shell server.
Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state.
# journalctl -u ssh.service
-- Logs begin at Tue 2015-03-31 17:29:27 CEST, end at Tue 2015-03-31 17:30:36 CEST. --
Mar 31 17:29:27 mirtuel sshd[424]: Server listening on 0.0.0.0 port 22.
Mar 31 17:29:27 mirtuel sshd[424]: Server listening on :: port 22.
Mar 31 17:29:29 mirtuel sshd[424]: Received SIGHUP; restarting.
Mar 31 17:29:29 mirtuel sshd[424]: Server listening on 0.0.0.0 port 22.
Mar 31 17:29:29 mirtuel sshd[424]: Server listening on :: port 22.
Mar 31 17:30:10 mirtuel sshd[1147]: Accepted password for roland from 192.168.1.129 port 38742 ssh2
Mar 31 17:30:10 mirtuel sshd[1147]: pam_unix(sshd:session): session opened for user roland by (uid=0)
Mar 31 17:30:35 mirtuel sshd[1180]: /etc/ssh/sshd_config line 28: unsupported option "yess".
Mar 31 17:30:35 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a
Mar 31 17:30:35 mirtuel systemd[1]: Unit ssh.service entered failed state.
Mar 31 17:30:35 mirtuel sshd[1182]: /etc/ssh/sshd_config line 28: unsupported option "yess".
Mar 31 17:30:35 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a
Mar 31 17:30:35 mirtuel systemd[1]: Unit ssh.service entered failed state.
Mar 31 17:30:35 mirtuel sshd[1184]: /etc/ssh/sshd_config line 28: unsupported option "yess".
Mar 31 17:30:35 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a
Mar 31 17:30:35 mirtuel systemd[1]: Unit ssh.service entered failed state.
Mar 31 17:30:36 mirtuel sshd[1186]: /etc/ssh/sshd_config line 28: unsupported option "yess".
Mar 31 17:30:36 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a
Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state.
Mar 31 17:30:36 mirtuel sshd[1188]: /etc/ssh/sshd_config line 28: unsupported option "yess".
Mar 31 17:30:36 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a
Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state.
Mar 31 17:30:36 mirtuel systemd[1]: ssh.service start request repeated too quickly, refusing to start.
Mar 31 17:30:36 mirtuel systemd[1]: Failed to start OpenBSD Secure Shell server.
Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state.
# vi /etc/ssh/sshd_config
# systemctl start ssh.service
# systemctl status ssh.service
● ssh.service - OpenBSD Secure Shell server
   Loaded: loaded (/lib/systemd/system/ssh.service; enabled)
   Active: active (running) since Tue 2015-03-31 17:31:09 CEST; 2s ago
  Process: 1023 ExecReload=/bin/kill -HUP $MAINPID (code=exited, status=0/SUCCESS)
 Main PID: 1222 (sshd)
   CGroup: /system.slice/ssh.service
           └─1222 /usr/sbin/sshd -D
# 
Dopo aver controllato lo stato del servizio (fallito), siamo andati a controllare i registri; indicano un errore nel file di configurazione. Dopo aver modificato il file di configurazione e sistemato l'errore, riavviamo il servizio, quindi verifichiamo che sia effettivamente in funzione.

9.1.2. Il sistema di init System V

Il sistema di init System V (che chiameremo init per brevità) esegue diversi processi, seguendo le istruzione del file /etc/inittab. Il primo programma che viene eseguito (che corrisponde al passo sysinit) è /etc/init.d/rcS, uno script che esegue tutti i programmi contenuti nella directory /etc/rcS.d/.
Tra questi, si trovano successivamente i programmi incaricati di:
  • configurare la tastiera della console;
  • caricare i driver: la maggior parte dei moduli del kernel vengono caricati dal kernel stesso, al rilevamento dell'hardware, altri driver aggiuntivi vengono caricati in seguito automaticamente se i moduli corrispondenti sono elencati nel file /etc/modules;
  • verificare l'integrità dei file system;
  • montare partizioni locali;
  • configurare la rete;
  • montare file system di rete (NFS).
In seguito a questa fase, subentra init e avvia quei programmi attivati nel runlevel predefinito (che di solito è il runlevel 2). Viene eseguito /etc/init.d/rc 2, uno script che lancia tutti i servizi che sono elencati in /etc/rc2.d/ ed i cui nomi iniziano con la lettera «S». Il numero a due cifre che segue era storicamente utilizzato per definire l'ordine in cui i servizi dovevano essere avviati, ma al giorno d'oggi il sistema di avvio predefinito utilizza insserv, che pianifica tutto automaticamente in base alle dipendenze degli script. Ogni script di avvio dichiara in tal modo le condizioni che devono essere soddisfatte per avviare o arrestare il servizio (per esempio, se si deve avviare prima o dopo un altro servizio); init poi li esegue nell'ordine che soddisfa queste condizioni. La numerazione statica degli script quindi non è più presa in considerazione (ma devono sempre avere un nome che inizia con una «S» seguita da due cifre ed il nome effettivo dello script usato per le dipendenze). In generale, i servizi di base (come la registrazione con rsyslog, o l'assegnazione di porte con portmap) vengono avviati per primi, seguiti dai servizi standard e dall'interfaccia grafica (gdm3).
Questo sistema di avvio basato su dipendenze consente di automatizzare la rinumerazione, che potrebbe risultare piuttosto noiosa se dovesse essere effettuata manualmente, e limita i rischi di errore umano, poiché la pianificazione viene effettuata secondo i parametri indicati. Un altro vantaggio è che i servizi possono essere avviati in parallelo quando sono indipendenti l'uno dall'altro, e quindi è possibile accelerare il processo di avvio.
init distingue tra diversi runlevel, in modo da poter passare da uno all'altro con il comando telinit nuovo-livello. Immediatamente, init esegue ancora una volta /etc/init.d/rc con il nuovo runlevel. Questo script quindi avvia i servizi mancanti e ferma quelli che non sono più desiderati. Per fare ciò, fa riferimento al contenuto di /etc/rcX.d (dove X rappresenta il nuovo runlevel). Gli script che iniziano con «S» (come in «Start») sono i servizi da avviare, quelli che iniziano con «K» (come in «Kill») sono i servizi che devono essere arrestati. Lo script non avvia alcun servizio che era già attivo nel runlevel precedente.
Per impostazione predefinita, System V init in Debian utilizza quattro diversi runlevel:
  • Il livello 0 è utilizzato solo temporaneamente, mentre il computer si sta spegnendo. Come tale, esso contiene solo molti script «K».
  • Il livello 1, noto anche come modalità utente singolo, corrisponde al sistema in modalità degradata; include solo i servizi basilari, ed è destinato ad operazioni di manutenzione in cui le interazioni con gli utenti ordinari non sono desiderate.
  • Il livello 2 è il livello per il normale funzionamento, che include servizi di rete, un'interfaccia utente grafica, accesso utenti, ecc.
  • Il livello 6 è simile al livello 0, tranne che è utilizzato durante la fase di arresto che precede un riavvio.
Esistono altri livelli, in particolare da 3 a 5. In modo predefinito sono configurati per operare allo stesso modo del livello 2, ma l'amministratore può modificarli (aggiungendo o eliminando script nella corrispondente directory /etc/rcX.d) per adattarli a particolari esigenze.
Sequenza di avvio di un computer Linux con System V init

Figura 9.2. Sequenza di avvio di un computer Linux con System V init

Tutti gli script contenuti nelle varie directory /etc/rcX.d sono solo collegamenti simbolici, creati con l'installazione del pacchetto per il programma update-rc.d, che puntano agli script reali che vengono memorizzati in /etc/init.d/. L'amministratore può regolare i servizi disponibili in ogni runlevel attraverso il comando update-rc.d con i parametri corretti. La pagina di manuale di update-rc.d(1) descrive la sintassi in dettaglio. Notare che la rimozione di tutti i collegamenti simbolici (con il parametro remove) non è un buon metodo per disabilitare un servizio. Si dovrebbe invece semplicemente configurare quel servizio per non essere lanciato in quel particolare runlevel (pur conservando le chiamate corrispondenti a fermarlo nel caso in cui il servizio viene eseguito nel runlevel precedente). Dal momento che update-rc.d ha un'interfaccia un po' complicata, può essere preferibile usare rcconf (presente nel pacchetto rcconf) che fornisce un'interfaccia più intuitiva.
Infine, init avvia i programmi di controllo per le varie console virtuali (getty). Visualizza un prompt, in attesa di un nome utente, poi esegue login utente per iniziare una sessione.