%% 
%% Dispense corso amministrazione
%%
%% Copyright (C) 2004-2018 Simone Piccardi and Truelite Srl. 
%%
%% This work is licensed under the Creative Commons Attribution-ShareAlike 4.0
%% International License. To view a copy of this license, visit
%% \url{http://creativecommons.org/licenses/by-sa/4.0/} or send a letter to
%% Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
%%
%% S. Piccardi Jan. 2004
%% 
%% ordadmin.tex: amministrazione ordinaria
%%

\chapter{Amministrazione ordinaria del sistema}
\label{cha:ordinary_admin}



\section{Archiviazione e backup}
\label{sec:adv_backup}

\index{backup|(}

Una delle attività fondamentali della amministrazione di un sistema è quella
dei backup. In questa sezione, dopo una introduzione generale sugli scopi ed i
criteri da usare per effettuare i backup, prenderemo in esame i programmi per
la gestione degli archivi di dati per la gestione dei backup e la duplicazione
dei dati dei dispositivi e quello della gestione dei nastri. Ci limiteremo
comunque ai programmi di base che si possono impiegare per eseguire i backup
di una singola macchina, per esigenze più complesse esistono programmi
dedicati alla esecuzione di backup via rete di interi gruppi di macchine, come
Bacula, Amanda o BackupPC.


\subsection{Criteri generali per il backup}
\label{sec:adv_backup_criteria}

Quella dei backup è probabilmente la più importante responsabilità di ogni
sistemista.  Nel mondo dell'informatica i dati sono il principale prodotto del
lavoro svolto, e la perdita degli stessi significa spesso la perdita di grandi
quantità di ore di lavoro. Per questo motivo occorre prendere le opportune
misure per assicurarsi contro questa evenienza, ed il backup è la principale
di queste misure.

Ci possono essere varie ragioni per cui si possono perdere i propri dati, in
generale si applica una classificazione che tende a dividerle in quattro
categorie principali: disastri naturali, attività umane, errori del software e
guasti dell'hardware. Ciascuna di queste categorie comporta rischi specifici e
richiede opportune contromisure.

Oggi l'hardware tende ad essere sufficientemente affidabile, ciò non di meno i
guasti continuano ad esserci, e la sfortuna è in agguato per farli avvenire
nel peggior momento possibile. In genere in questo caso i dispositivi più
critici sono i dischi, che per quanto ben costruiti hanno una loro fragilità
meccanica e sono comunque dispositivi basati sulla lettura di campi magnetici
di bassissima intensità, per cui il rischio di malfunzionamento, per quanto
ridotto, non è trascurabile. Nel caso dei dischi una possibile contromisura
contro il malfunzionamento è quello dell'uso del RAID (vedi
sez.~\ref{sec:disk_RAID}), ma questa copre soltanto un caso particolare di
rischio, i guasti dell'hardware, e non le altre ragioni (come la cancellazione
accidentale) per cui sono necessari i backup.

Al contrario dell'hardware l'affidabilità del software non sembra subire
particolari miglioramenti, ed un programma solido, affidabile e sicuro è
sempre un caso piuttosto raro. Inoltre l'affidabilità di un singolo programma
è relativamente inutile se un altro va a sovrascrivere per errore i suoi
dati. In questo la struttura di un sistema Unix, con la separazione dei
privilegi, e l'uso di utenti distinti può essere di aiuto, ma di nuovo non è
la soluzione al problema di eventuali perdite di dati. 

L'affidabilità delle persone è sempre una variabile difficile da quantificare,
sia in termini delle competenze che riducano l'eventualità di errori nelle
operazioni, che però possono sempre accadere anche al più esperto degli
amministratori, sia nella onestà e correttezza della singola persona rispetto
al caso di eventuali azioni dolose che possono causare, direttamente o
indirettamente, la distruzione dei dati o il danneggiamento dei relativi
supporti.

Per quanto riguarda i disastri naturali, ed altre eventualità remote
completamente distruttive di ogni tipo, occorre sempre valutare quanto la
distruzione completa dei propri dati all'interno di un evento catastrofico
possa incidere in termini di perdite complessive e determinare se vale la pena
di prevedere delle contromisure specifiche per tali evenienze, che spesso
comportano un forte aggravio di costi sia in termini di attrezzature che di
gestione.

Come accennato, mantenere dei backup è la strategia più semplice ed efficace
per proteggersi dalle molteplici evenienze che possono causare la perdita di
dati. Avere a disposizione copie multiple dei propri dati rende meno critica
la perdita di una di esse, ed il costo della perdita si riduce semplicemente a
quello del ripristino degli stessi dal backup, e non alla ricreazione da zero
degli stessi.

Perché questa strategia sia efficace occorre però che i backup siano
effettuati in maniera appropriata; come ogni altra cosa del mondo reale
infatti essi possono fallire ed al solito tenderanno a farlo nel peggior modo
e momento possibili, per cui potreste trovarvi senza disco e scoprire che un
nastro è illeggibile, o che vi siete dimenticati di inserire nel backup alcune
informazioni essenziali, o che l'unica unità a nastro in grado di rileggere i
vostri backup si è rotta pure lei.

Per questo motivo nell'effettuare dei backup il primo punto da prendere in
considerazione è quello di pianificare una opportuna strategia. Ci sono
infatti parecchie variabili da tenere sotto controllo, come la quantità di
dati che si vogliono mantenere, la frequenza dei backup, il periodo che si
intende coprire con il backup, il mezzo utilizzato, ed infine le modalità di
gestione dei backup stessi.

In genere un primo passo è quello di definire cosa si intende inserire nel
backup: ad esempio non è quasi mai strettamente indispensabile effettuare un
backup dei programmi di sistema, se non nel caso in cui una reinstallazione da
zero non comporti un carico di lavoro eccessivo, mentre può essere importante
salvare delle configurazioni ottenute come risultato finale di parecchie ore
di lavoro. Sono senz'altro da salvare tutti i dati di sistema, gli archivi
della posta e di un eventuale database e del web, e quant'altro non è
replicabile in maniera automatica, insieme ai dati personali dei singoli
utenti. Questo ad esempio vuol dire, nell'ambito di un sistema GNU/Linux, che
si devono salvare i contenuti delle directory \texttt{/etc}, \texttt{/var} e
\texttt{/home}, mentre non è necessario salvare quelli di \texttt{/usr}.

Una volta determinata la dimensione totale dei dati che si vogliono
archiviare, occorre stabilire anche il periodo di tempo che si intende coprire
con i backup, e la frequenza con cui si effettuano questi ultimi. Se infatti
si avesse un sistema di backup contenente solo le informazioni necessarie a
ripristinare la situazione ad un certo istante, non si potrebbero recuperare
eventuali dati cancellati in precedenza. Nella pratica invece il caso
più comune di recupero di dati da un backup è proprio quello di dati
cancellati inavvertitamente, che, se assenti alla data
dell'ultimo backup disponibile, sarebbero irrimediabilmente perduti.

Questo comporta che deve essere determinata la frequenza con cui si vogliono
effettuare i backup, in modo da poter essere in grado di ricostruire la
situazione dei propri dati ad istanti diversi nel passato. La frequenza dei
backup dipende ovviamente anche da quella con cui variano i dati: in genere le
configurazioni di sistema o un indirizzario variano senz'altro molto meno
della posta elettronica o dei dati di accesso a servizi web. Un altro fattore
che incide sulla frequenza è il tempo che occorre a creare il backup, dato che
se questo dovesse eccedere il periodo fra due backup successivi si avrebbe una
situazione in cui un backup non si completa prima dell'inizio del successivo,
e non avrebbe senso usare una frequenza maggiore.

Infine la scelta del periodo da coprire con i backup dipende dall'uso degli
stessi, ad esempio se servono solo a mantenere una copia di riserva che
permetta il recupero di eventuali cancellazioni accidentali passate
inosservate, o se si vuole mantenere una storia completa per ragioni di
archiviazione. Ovviamente più lungo sarà il periodo, più risorse dovranno
essere utilizzate nella manutenzione dei backup. Inoltre anche qualora non
esistano esigenze di archiviazione, occorre tenere presente che se una
cancellazione accidentale è rimasta inosservata per un periodo di tempo
superiore a quello di cui si mantiene il backup, questa non sarà più
recuperabile.

Un'altra decisione cruciale nella strategia di backup è la scelta del supporto
da utilizzare per gli stessi. Le variabili in gioco sono il costo,
l'affidabilità, la velocità e l'utilizzabilità. Il costo incide direttamente
sulla quantità di dati che si possono salvare, per cui è opportuno avere un
mezzo poco costoso.  L'affidabilità invece è fondamentale, dato che un backup
inaffidabile è assolutamente inutile, ma l'affidabilità dipende anche dal tipo
di problema che ci si trova ad affrontare: ad esempio i dischi sono
affidabili, ma a lungo non sono stati considerati adatti come mezzi di backup
in quanto vincolati ad essere residenti nello stesso computer che contiene i
dati originali, che può andare distrutto, danneggiato o manomesso.

La velocità è senz'altro utile, ma diventa cruciale solo qualora un mezzo
troppo lento rendesse impossibile effettuare i backup con la frequenza
necessaria.  L'utilizzabilità viene spesso data per scontata, ma occorre
invece riflettere ad esempio su quanto possa essere pericoloso avere uno
splendido sistema di backup perfettamente funzionante, che funziona però solo
con una vecchia scheda hardware fuori produzione.

Tenendo conto di tutte queste caratteristiche a lungo gli unici supporti
considerati appropriati per i backup sono stati i nastri magnetici. I CD o i
DVD masterizzati infatti, benché funzionali e relativamente poco costosi,
hanno grossi problemi di stabilità nel lungo periodo, i supporti si
deteriorano piuttosto rapidamente, e non danno garanzie già dopo pochi anni,
per questo sono inadatti per l'archiviazione.

La soluzione classica era quella di utilizzare unità a nastro SCSI (vedi
sez.~\ref{sec:SCSI_interface}).  I nastri infatti hanno una ottima stabilità
nel tempo se si usano supporti di qualità (oggi gli LTO). I nastri inoltre
consentono di immagazzinare grandi quantità di dati in relazione alle
dimensioni medie dei dischi, anche se oggi, con l'espandersi della capacità di
questi ultimi, questo è sempre meno vero.  Infine le interfacce SCSI hanno
dimostrato di mantenersi utilizzabili nell'evoluzione della tecnologia, il
principale difetto resta il costo piuttosto elevato.

Nei tempi più recenti, con la disponibilità a basso costo di dischi
rimuovibili su bus USB, le cose stanno cambiando. Questi infatti si stanno
affermando sempre di più come alternativa ai nastri, rispetto ai quali
presentano l'innegabile vantaggio di un costo iniziale nettamente inferiore,
non essendo necessario per il loro funzionamento alcun dispositivo
aggiuntivo. Lo svantaggio può esserci in caso di necessità di archiviazione di
grandi quantità di dati, per i quali i nastri presentano una maggiore
robustezza meccanica, e, su numeri elevati dei supporti da mantenere, un costo
inferiore.

Oltre alla scelta dei supporti una strategia di backup deve comunque anche
prevedere la definizione delle modalità di conservazione degli stessi. Ad
esempio può non essere troppo saggio tenere i propri supporti in un armadio
nel corridoio, sotto una vecchia tubatura del riscaldamento che potrebbe
rompersi. Inoltre qualunque sia la modalità di stoccaggio utilizzata occorre
anche prevedere verifiche periodiche del funzionamento dei backup (effettuando
dei ripristini di controllo), dato che accorgersi che qualcosa è andato storto
nel momento del bisogno non è molto simpatico. 

A tal proposito viene citato l'esempio di un sistemista di un paese del nord
Europa che aveva accuratamente pianificato tutta la sua strategia, prevedendo
anche lo stoccaggio dei nastri in un locale sicuro in una locazione
remota. Questi si accorse la prima volta che dovette recuperare dei dati che
tutti i suoi nastri erano stati rovinati dal campo magnetico generato dai fili
del riscaldamento del sedile della macchina su cui li appoggiava quando li
portava al sito di stoccaggio.

Una volta esaminati i principali rischi da cui ci si deve difendere,
determinati quali dati si intende proteggere e prese in considerazione le
caratteristiche delle possibili risorse per eseguire questa operazione si
potrà iniziare a pianificare una strategia di backup. In genere si
classificano i backup in tre diverse categorie generali:

\begin{basedescript}{\desclabelwidth{1.5cm}\desclabelstyle{\nextlinelabel}}
\item[\textsl{backup completo} (\textit{full backup})] si chiama così la
  realizzazione di una copia completa di tutti i dati che interessano,
  eseguita ad un certo istante. Il vantaggio di disporre di un backup completo
  è che questo è sufficiente da solo a garantire il ripristino dei dati al
  momento in cui è stato eseguito. Lo svantaggio è che in genere l'esecuzione
  di una copia completa di tutti i dati richiede un tempo non trascurabile;
  inoltre per poter garantire la copertura con il backup per un certo periodo
  di tempo in genere occorre duplicare una grande quantità di dati che per lo
  più saranno identici, utilizzando in maniera sostanzialmente inefficiente le
  risorse su cui si salvano i dati. Esistono però soluzioni specifiche che
  consentono di mantenere comunque una copia unica degli stessi file, posto
  che questi siano mantenuti su dei dischi, se si usano i nastri questo tipo
  di strategia non può essere invece realizzata.

\item[\textsl{backup incrementale} (\textit{incremental backup})] si chiama
  così la realizzazione di una copia di tutti i dati che sono stati modificati
  a partire dall'ultimo backup eseguito (completo o incrementale che sia). In
  questo caso cioè non si ha una copia completa dei dati, ma solo di quello
  che è cambiato rispetto all'ultima esecuzione, per cui per poter eseguire un
  ripristino sarà necessario non soltanto avere l'ultimo backup incrementale
  eseguito, ma anche tutti quelli precedenti fino all'ultimo backup completo
  disponibile.  Il vantaggio dei backup incrementali è che permettono di
  limitare l'occupazione di risorse ed i tempi di esecuzione dei backup,
  mantenendo la capacità di ricostruire la situazione ad un dato istante per
  un certo periodo di tempo senza dover registrare tutte le volte l'insieme
  completo dei dati.  Lo svantaggio è che si complica la procedura di recupero
  dei dati, che necessiterà di un numero di passaggi crescente con il numero
  di backup incrementali coinvolti, e si diminuisce l'affidabilità perché il
  fallimento di un backup incrementale renderà inutilizzabili tutti quelli
  successivi basati su di esso.

\item[\textsl{backup differenziale} (\textit{differential backup})] si chiama
  così la realizzazione di una copia di tutti i dati che sono stati modificati
  a partire dall'ultimo \textsl{backup completo}. Un backup differenziale è un
  compromesso fra un backup completo ed un backup incrementale: non richiede
  di avere tutti i backup parziali precedenti dall'ultimo backup completo, ma
  solo quest'ultimo. Pertanto si riduce l'occupazione delle risorse ed il
  tempo impiegato rispetto ad un backup completo, ma in maniera inferiore
  rispetto a quanto si sarebbe ottenuto con un backup incrementale. Rispetto a
  quest'ultimo però, non essendo necessari i backup differenziali precedenti,
  ma solo l'ultimo backup completo, si ha il vantaggio di una maggior
  sicurezza e di una procedura di ripristino più semplice.
\end{basedescript}

In generale una strategia di backup si basa sulla opportuna combinazione di
backup completi e backup incrementali o differenziali. Si stabilisce una
opportuna cadenza a cui eseguire dei backup completi, e si copre il periodo di
tempo dall'uno all'altro con backup incrementali (o differenziali). In un
mondo ideale, con risorse infinite, la soluzione è eseguire una sequenza
continua di backup completi mantenuti indefinitamente, così da avere il
massimo della sicurezza. 

Nel mondo reale però ci si scontra con alcuni limiti, il primo dei quali è il
tempo necessario alla esecuzione del backup: questo già pone un limite
insormontabile alla frequenza dei backup completi.  Si tenga presente inoltre
che in molti casi l'esecuzione del backup richiede l'interruzione del servizio
di cui si stanno salvando i dati e non è detto che si possa restare in questo
stato troppo a lungo. Questo avviene perché, ad esempio con i database, se si
copiano i dati a servizio attivo questi potrebbero essere in uno stato
inconsistente, a causa dell'accesso concorrente fatto dal programma che esegue
il backup, che li legge, e di quello che eroga il servizio, che li modifica.

Questo è il motivo per cui in genere le procedure di backup vengono eseguite a
notte fonda, onde diminuire al massimo gli eventuali disagi causati dal fermo
dei servizi. Per risolvere questo problema può essere di grande aiuto l'uso
dei cosiddetti \textit{snapshot} del filesystem, in cui si genera una sorta di
\textsl{fotografia} ad un certo istante dello stato dei propri file,
accessibile in maniera opportuna anche successivamente (ne vedremo un esempio
in sez.~\ref{sec:disk_LVM}). In questo caso si potrà fermare il servizio solo
per il tempo necessario a creare lo \textit{snapshot} per poi eseguire il
backup su di esso in tutta calma.

Il secondo limite è quello dello spazio disponibile per l'archiviazione dei
dati del backup, che non è mai infinito, ed in genere tende a finire assai
prima di quanto si era previsto inizialmente. Per questo motivo si ricorre
quasi sempre a backup incrementali, che oltre a consentire una esecuzione più
veloce limitano la quantità di spazio occupato.

A titolo di esempio una strategia di backup comunemente utilizzata è quella di
effettuare backup incrementali a frequenza giornaliera, intervallati da backup
completi a cadenza settimanale, mantenendo uno storico mensile, ed
eventualmente archiviando i backup mensili per un periodo di tempo più o meno
lungo a secondo delle esigenze di ``\textit{data retention}'' che si possono
avere.

Si ricordi infine, ed è opportuno sottolinearlo una seconda volta dato che
questo aspetto viene spesso sottovalutato, che una strategia di backup non può
definirsi tale se non prevede anche in maniera esplicita, oltre alla
esecuzione dei backup, una procedura per la verifica periodica del loro
ripristino, che assicuri l'effettiva disponibilità dei dati in essi archiviati
quando questi dovranno essere recuperati.

\index{backup|)}


\subsection{I comandi per la gestione di archivi di file}
\label{sec:tar_cpio}

La modalità più comune per eseguire un backup è quella di creare un archivio
contenente i file interessati. Benché sia possibile anche copiare il
contentuto di una intera directory (e di tutte le sue sottodirectory) con
\texttt{cp} in genere avere tutto su un singolo file rende più semplici le
operazioni di spostamento dei dati e soprattutto consente, usando il programma
opportuno, di conservare anche i metadati dei file (come permessi,
proprietario, tempi, ecc.) che con una copia ordinaria sarebbero supportati
soltanto se questa viene effettuata su un filesystem di tipo Unix. Inoltre
l'uso di un archivio su un singolo file consente di effettuare la copia anche
su dispositivi, come i nastri, su cui non è supportato un filesystem.

Il comando più usato per la gestione di archivi di file è
\index{comando!\texttt{tar}} \texttt{tar}, chiamato così dall'inglese
``\textit{\textbf{t}ape \textbf{ar}chive}'' dato che è nato proprio per
archiviare i file su nastro magnetico. Al di là del suo uso per la creazione
di archivi, \texttt{tar} è anche il programma più diffuso per la distribuzione
di pacchetti di software dai sorgenti (come vedremo in
sez.~\ref{sec:install_tarball}).  La caratteristica principale del comando è
che è in grado di salvare su un file di archivio, e ripristinare da esso, il
contenuto e la struttura di una o più directory, mantenendo invariati anche i
metadati dei file.

Il comando \texttt{tar} supporta una grande varietà di opzioni ed argomenti, e
la versione GNU è stata dotata di una serie di ulteriori estensioni. In
generale però si possono distinguere le opzioni del comando in due classi
principali: quelle che indicano delle \textsl{operazioni} e quelle che
specificano dei \textsl{parametri}.  In ogni invocazione si può specificare
non più di una operazione, mentre si possono avere un numero qualunque di
parametri.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|l|p{8cm}|}
    \hline
    \multicolumn{2}{|c|}{\textbf{Opzione}} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-c} & \texttt{-{}-create} & crea un nuovo archivio.\\ 
    \texttt{-x} & \texttt{-{}-extract}& estrae i file da un archivio.\\ 
    \texttt{-t} & \texttt{-{}-list}   & elenca i file contenuti in un
                                        archivio.\\ 
    \texttt{-A} &\texttt{-{}-concatenate}& aggiunge un archivio in coda ad un
                                        altro.\\  
    \texttt{-d} & \texttt{-{}-diff}   & confronta i membri di un archivio con
                                        la controparte sul filesystem e
                                        riporta ogni differenza in dimensioni, 
                                        permessi, proprietari e tempi.\\ 
    \texttt{-u} & \texttt{-{}-update} & aggiunge file in coda all'archivio, ma 
                                        solo se sono più recenti della
                                        versione già presente nell'archivio o
                                        se non sono presenti in esso.\\
    \texttt{-r} & \texttt{-{}-append} & aggiunge file in coda all'archivio.\\ 
                & \texttt{-{}-delete} & cancella i file da un archivio (questo
                                        non può funzionare sui nastri).\\ 
                & \texttt{-{}-compare}& identica a \texttt{-{}-diff}.\\ 
                & \texttt{-{}-get }   & identica a \texttt{-{}-extract}.\\ 
    \hline
  \end{tabular}
  \caption{Operazioni del comando \texttt{tar}.}
  \label{tab:ord_tar_operation}
\end{table}

Il comando prevede tre operazioni principali, \texttt{-c} per creare un
archivio, \texttt{-t} per verificarne il contenuto, e \texttt{-x} per
estrarlo, ma le operazioni sono in totale otto, e sono illustrate in
tab.~\ref{tab:ord_tar_operation}, sia in forma breve che estesa. Si è usata la
sintassi delle opzioni nella forma prevista dal progetto GNU, ma \texttt{tar}
è uno dei comandi storici di Unix, e ne esistono molte versioni. Per questo
anche la versione GNU, la sola che tratteremo, supporta varie sintassi, ed in
particolare si può sempre fare a meno di utilizzare il ``\texttt{-}'' quando
si specifica una opzione in forma breve.

Come accennato oltre alle operazioni \texttt{tar} supporta una enorme quantità
di opzioni che modificano il comportamento del programma. Di queste ne
esistono due che sono di uso comune e vengono utilizzate quasi sempre; la
prima è \texttt{-v} (o \texttt{-{}-verbose}), che aumenta la
\textsl{prolissità} del comando, facendogli stampare a video durante
l'esecuzione molte più informazioni, ad esempio la lista dei file inseriti o
estratti dall'archivio.  É in genere possibile aumentare ulteriormente la
quantità di informazioni stampate inserendo la stessa opzione una seconda
volta.

La seconda è \texttt{-f} (o \texttt{-{}-file}) che serve a specificare il nome
del file da usare come archivio da cui leggere o su cui scrivere. Il comando
infatti, se non la si utilizza, usa come default rispettivamente lo
\textit{standard input} e lo \textit{standard output}, a meno che non sia
stata definita la variabile di ambiente
\index{variabili!di~ambiente!\texttt{TAPE}} \texttt{TAPE}, nel qual caso viene
usato il dispositivo indicato in detta variabile. Per evitare confusione è
pertanto opportuno specificare sempre esplicitamente il nome dell'archivio con
questa opzione.

Si tenga presente che quando si esegue il backup su un nastro, (come vedremo
in sez.~\ref{sec:SCSI_interface} in genere i nastri vengono utilizzati tramite
l'interfaccia SCSI) occorre anche indicarne per \texttt{TAPE} o come argomento
per \texttt{-f} il corretto file di dispositivo, infatti in tal caso i valori
possibili possono essere \texttt{/dev/st0} o \texttt{/dev/nst0} (nel caso di
un solo nastro, se ve ne sono più di uno vengono numerati progressivamente) a
seconda che si voglia il riavvolgimento automatico o meno. In genere si usa
\texttt{/dev/nst0} quando si sa che si dovranno eseguire più scritture per
evitare il riavvolgimento del nastro.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{10cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-b \textsl{N}} & imposta la dimensione dei blocchi di
                             trasferimento (in multipli di 512 byte), usata
                             per l'I/O su nastro.\\ 
    \texttt{-C \texttt{\textsl{dir}}} & esegue le operazioni sulla directory
                  \texttt{\textsl{dir}} invece che su quella corrente.\\ 
    \texttt{-f \textsl{file}} & indica il file di archivio a cui fare
                                riferimento con l'operazione corrente.\\
    \texttt{-g \textsl{list}} & esegue il comando in modalità incrementale nel
                  nuovo formato, appoggiandosi alla lista
                  \texttt{\textsl{list}}.\\  
    \texttt{-G} & esegue il comando in modalità incrementale (vecchio
                  formato).\\  
    \texttt{-j} & comprime al volo l'archivio utilizzando il programma
                  \texttt{bzip2}.\\ 
    \texttt{-J} & comprime al volo l'archivio utilizzando il programma
                  \texttt{xz}.\\ 
    \texttt{-M} & opera su un archivio multivolume.\\ 
    \texttt{-O} & estrae i file sullo \textit{standard output}.\\ 
    \texttt{-v} & aumenta la \textsl{prolissità} del comando facendogli
                  stampare a video più informazioni riguardo le operazioni
                  correnti.\\
    \texttt{-z} & comprime al volo l'archivio utilizzando il programma
                  \texttt{gzip}.\\ 
    \hline
  \end{tabular}
  \caption{Principali opzioni generiche del comando \texttt{tar}.}
  \label{tab:tar_general_options}
\end{table}

Un'altra delle funzionalità offerte da \texttt{tar} è quella che consente,
appoggiandosi ai comandi trattati in sez.~\ref{sec:cmd_file_filter}, di
eseguire in maniera automatica la compressione (in creazione) e la
decompressione (in estrazione) degli archivi. A tale scopo l'opzione usata più
comunemente è \texttt{-z} che effettua una compressione con \texttt{gzip}, ed
è invalso l'uso comune di utilizzare una ulteriore estensione \texttt{.gz} al
nome dell'archivio (che diventa qualcosa del tipo \texttt{archivio.tar.gz})
per identificare i file, detti in gergo ``\textit{tarball}'', creati con
questa opzione. Alternativamente si può utilizzare l'opzione \texttt{-j}, che
consente di utilizzare il programma \texttt{bzip2} al posto di \texttt{gzip},
e in questo caso per gli archivi si usa l'ulteriore estensione \texttt{.bz2}
ed analogamente con \texttt{-J} viene usato \texttt{xz} e gli archivi usano
l'estensione \texttt{.xz}. Si può infine specificare un programma di
compressione qualunque con l'opzione estesa \texttt{-{}-use-compress-program}
seguita dal nome del programma da usare.

Come accennato per creare un archivio il comando necessita dell'opzione
\texttt{-{}-create} o \texttt{-c}; in questo caso dovrà anche essere
specificato con \texttt{-f} il nome del file su cui saranno archiviati i file,
e se non si comprime di norma si utilizza l'estensione \texttt{.tar} per
identificare questi file. L'opzione prende anche il valore ``\texttt{-}'' per
indicare rispettivamente \textit{standard input} e \textit{stardard output}.
Date queste due opzioni il comando prende come argomenti una lista dei singoli
file da archiviare, se però fra questi si inserisce una directory il comando
archivierà anche il contenuto di quest'ultima, e di tutte le directory
sottostanti. Ad esempio si possono archiviare alcuni file con:
\begin{Console}
piccardi@anarres:~/truedoc/corso$ \textbf{tar -cvf dispense.tar *.tex}
advadmin.tex
appendici.tex
...
stradmin.tex
struttura.tex
\end{Console}
%$
e si noti come si sia usata anche l'opzione \texttt{-v} per stampare la lista
dei file archiviati; allo stesso modo si potrà archiviare tutta una directory
con:
\begin{Console}
piccardi@anarres:~/truedoc$ \textbf{tar -cvf dispense.tar corso}
corso/
corso/struttura.aux
corso/esercizi.txt
corso/struttura.tex
corso/shell.aux
corso/images/
corso/images/menuconfig1.png
corso/images/lvm_struct.eps
...
corso/corso.tex
corso/ringraziamenti.tex
\end{Console}
%$
e si noti come in questo caso vengano archiviate ricorsivamente anche tutte le
directory sottostanti ed il relativo contenuto.

Si tenga presente che quando si crea un archivio con \texttt{-c} il file di
destinazione viene sovrascritto, se si vuole invece aggiungere dei file ad un
archivio preesistente occorre usare l'opzione \texttt{-r}. Inoltre, a meno di
non specificare un pathname assoluto, il file viene creato nella directory
corrente, questo significa anche che se quest'ultima è inclusa nell'archivio
\texttt{tar} si troverà ad affrontare il problema di come archiviare
l'archivio stesso. Il comando è sufficientemente scaltro da accorgersi di
questa situazione ed evitare di inserire nell'archivio che sta creando il file
dell'archivio stesso:
\begin{Console}
piccardi@anarres:~/truedoc$ \textbf{tar -cf dispense.tar .}
tar: ./dispense.tar: file is the archive; not dumped
\end{Console}
%$

Un'ultima caratteristica di \texttt{tar} è che qualora si utilizzino dei
pathname assoluti per indicare le directory o i file da archiviare, questi
verranno sempre salvati con un pathname relativo in cui la ``\texttt{/}''
iniziale viene eliminata, con un avviso al riguardo. Tutto ciò avviene perché
quando si vanno ad estrarre i dati da un archivio tutti i file in esso
contenuti vengono ripristinati a partire dalla directory corrente, ed anche se
se ne può specificare una diversa con l'opzione \texttt{-C}, l'estrazione
considera in ogni caso i pathname dei file contenuti nell'archivio come
relativi rispetto alla directory in cui essi vengono estratti, per evitare
sovrascritture dei file del sistema.

Una volta creato un archivio se ne potrà verificare il contenuto con
\texttt{-t} o \texttt{-{}-list} e di nuovo si dovrà utilizzare \texttt{-f} per
indicare il file contenente l'archivio, che in questo caso sarà letto. Se non
si passano altri argomenti il risultato sarà la stampa a video della lista di
tutti i file contenuti nell'archivio, anche senza la presenza dell'opzione
\texttt{-v}, specificando la quale si otterrà invece una lista in formato
esteso, analogo a quella ottenibile con \texttt{ls -l}. Si può verificare la
presenza di un singolo file o di una lista passando come argomento il nome (o
i nomi), si tenga presente però che in questo caso deve essere specificato il
nome completo del file così come è stato archiviato (quello stampato
dall'opzione \texttt{-v} in fase di creazione), il confronto infatti viene
eseguito solo nei termini della corrispondenza fra l'argomento ed il nome come
questo viene visto nell'archiviazione.

Per estrarre i dati inseriti in un archivio si deve utilizzare l'opzione
\texttt{-x} o \texttt{-{}-extract}, di nuovo è necessario specificare
l'archivio da cui si estraggono i file con \texttt{-f}. Come per la creazione
l'uso dell'opzione \texttt{-v} permette di vedere la lista dei file che
vengono estratti dall'archivio. L'estrazione avviene sempre nella directory
corrente, e qualora si siano archiviate intere directory ne viene ricreata
l'intera gerarchia. Se non si specifica nessun argomento il comando estrae il
contenuto completo dell'archivio, ma è possibile estrarre un singolo file
fornendone il nome (o il pathname se questo è collocato in una
sottodirectory), che si può ottenere dalla lista ottenuta con \texttt{-t}.

Si tenga presente infine che nell'estrazione il comando ricrea i file con
tutte le caratteristiche che essi avevano nel sistema su cui sono stati
creati; questo significa che vengono mantenuti i permessi, l'utente ed il
gruppo proprietario del file, utente e gruppo che nel sistema corrente possono
non esistere o essere del tutto diversi. Questi però vengono mantenuti
soltanto se l'archivio viene estratto dall'amministratore, gli utenti normali
infatti (vedi sez.~\ref{sec:struct_file_perm_comm}) non possono creare file
con proprietario diverso da se stessi e con gruppo diverso da quelli a cui
appartengono.

Di questo può essere necessario dover tenere conto quando si estraggono degli
archivi creati da altri (come quelli dei pacchetti sorgenti di cui parleremo
in sez.~\ref{sec:adv_package_admin}).  Inoltre dato che alcuni filesystem
(come il \texttt{vfat} di Windows) non supportano la presenza di permessi,
utenti e gruppi, il programma può lamentarsi dell'impossibilità di ricreare
questi attributi dei file. Un altro errore che viene segnalato, in caso di
impostazione sbagliata dell'ora di sistema, è quando i file che vengono creati
hanno dei tempi situati nel futuro.

Una delle capacità più interessanti di \texttt{tar} è quella di saper gestire
backup incrementali con l'uso dell'opzione \texttt{-g}. In questo caso
l'opzione prende come parametro il nome di un file, detto di
\textit{snapshot}, su cui \texttt{tar} si appoggia per determinare quali sono
stati i file modificati dall'ultimo backup. Per questo vengono utilizzate le
date di ultima modifica per cui è essenziale che il tempo di sistema (vedi
sez.~\ref{sec:cmd_time}) non sia stato modificato inopportunamente. 

Alla prima esecuzione, quando il file non esiste, questo viene creato ed alle
successive esecuzioni sarà possibile creare nuovi archivi contenenti solo i
file modificati dopo l'esecuzione del backup a cui fa riferimento il file di
\textit{snapshot}.  Ad ogni esecuzione con \texttt{-g} il file di
\textit{snapshot} viene aggiornato con tutti i cambiamenti intercorsi, per cui
sarà possibile, utilizzando sempre lo stesso file, eseguire backup
incrementali. È inoltre possibile, utilizzando una copia del file di
\textit{snapshot} creato la prima volta nell'esecuzione del backup completo,
effettuare backup differenziali.

Un secondo comando usato storicamente nei sistemi unix-like per la gestione
dell'archiviazione di file e directory è \index{comando!\texttt{cpio}}
\texttt{cpio}, che come \texttt{tar} permette di estrarre ed inserire file e
directory all'interno di un singolo file di archivio, per il quale è anche in
grado di usare lo stesso formato usato da \texttt{tar}. A differenza di
\texttt{tar} però \texttt{cpio} prende sempre come argomento di ingresso una
lista di file.

Il comando \texttt{cpio} ha tre modalità operative, che devono essere sempre
indicate ad ogni invocazione del programma. In modalità \textit{copy-out} il
comando copia i file dentro l'archivio e per attivarla deve essere specificata
l'opzione \texttt{-o} (o \texttt{-{}-create}). Il programma legge una lista di
file dallo \textit{standard input} e scrive l'archivio risultante sullo
\textit{standard output}, ma è uso comune generare la lista direttamente con
l'uso di \texttt{find} o \texttt{ls}. Si potranno cioè replicare le operazioni
di archiviazione viste in precedenza con \texttt{tar} con qualcosa del tipo:
\begin{Console}
piccardi@anarres:~/truedoc/corso$ \textbf{ls *.tex | cpio -ov > dispense.cpio}
advadmin.tex
appendici.tex
...
stradmin.tex
struttura.tex
3974 blocks
\end{Console}
%$
mentre per archiviare tutta una directory si dovrà eseguire:
\begin{Console}
piccardi@anarres:~/truedoc$ \textbf{find corso -depth -print | cpio -ov > dispense.cpio}
corso/struttura.aux
corso/esercizi.txt
corso/struttura.tex
corso/shell.aux
corso/images/menuconfig1.png
corso/images/lvm_struct.eps
...
corso/config.aux
corso/corso.tex
corso/ringraziamenti.tex
corso
80540 blocks
\end{Console}
%$

In modalità \textit{copy-in} il comando estrae i file contenuti in un archivio
o ne elenca il contenuto. Per attivare questa modalità deve essere specificata
l'opzione \texttt{-i} o \texttt{-{}-extract}. L'archivio viene letto dallo
\textit{standard input}, se non si specifica nessuna opzione tutti i file
vengono estratti, altrimenti tutti gli argomenti che non sono opzioni vengono
considerati come \textit{pattern} secondo la sintassi\footnote{con due
  eccezioni, vengono considerati validi come caratteri sui quali verificare
  una corrispondenza anche un ``\texttt{.}'' all'inizio del file e il
  carattere ``\texttt{/}'', così da considerare nella corrispondenza anche i
  file nascosti e intere sezioni di pathname.} del \textit{filename globbing}
della shell (vedi sez.~\ref{sec:shell_sintax}) e vengono estratti solo i file
che corrispondono.  Si tenga presente che di default il comando non crea le
directory, per cui se si vuole estrarre il contenuto di un archivio che
contiene un intero albero di directory occorre utilizzare l'opzione
\texttt{-d}. Una invocazione tipica in questa modalità è pertanto qualcosa del
tipo:
\begin{Example}
cpio -idv < dispense.cpio
\end{Example}

In modalità \textit{copy-pass} il comando copia dei file da una directory
ad un altra, combinando in sostanza le due modalità \textit{copy-in} e
\textit{copy-out} in un unico passo senza creare un archivio; per attivare
questa modalità deve essere specificata l'opzione \texttt{-p} o
\texttt{-{}-pass-through}. Il comando legge la lista dei file da copiare dallo
\textit{standard input} e li copia nella directory che deve essere specificata come
argomento non opzionale. Pertanto una invocazione tipica in questa modalità è
del tipo:
\begin{Example}
cpio -pdv < lista  directory
\end{Example}

Il comando, a parte quelle usate per specificarne la modalità di operazione,
supporta molte altre opzioni. In particolare con \texttt{-v} si richiede una
maggiore prolissità nelle operazioni, con la stampa dei nomi dei file che
vengono processati; con \texttt{-t} si richiede di stampare la lista del
contenuto di un archivio, con \texttt{-A} di aggiungere i file ad un archivio
esistente (invece di sovrascriverlo). 

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{10cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-0} & prende in ingresso una lista di stringhe terminate dal
                  carattere NUL (generabili con \texttt{find -print0}) per
                  permettere l'archiviazione di file il cui nome contiene
                  caratteri speciali.\\
    \texttt{-a} & ripristina il tempo di ultimo accesso sui file appena letti
                  perché non risultino tali.\\
    \texttt{-d} & ricrea le directory in cui si trovano i file.\\
    \texttt{-f} & copia solo i file che non corrispondono al pattern
                  specificato.\\
    \texttt{-F} & permette di specificare un nome di file da usare come
                  archivio al posto dello \textit{standard input} o dello 
                  \textit{standard output}.\\ 
    \texttt{-m} & preserva i precedenti tempi di ultima modifica quando ricrea
                  i file in fase di estrazione.\\
    \texttt{-t} & stampa la lista dei file contenuti nell'archivio.\\
    \texttt{-u} & sovrascrive eventuali file già esistenti con quelli
                  dell'archivio senza chiedere conferma.\\
    \texttt{-v} & stampa informazioni aggiuntive sui file che vengono
                  processati dal comando (in combinazione con \texttt{-t}
                  viene usato un formato analogo a quello di \texttt{ls -l}).\\
    \hline
  \end{tabular}
  \caption{Principali opzioni del comando \texttt{cpio}.}
  \label{tab:cpio_options}
\end{table}

L'elenco delle principali opzioni di \texttt{cpio} è riportato in
tab.~\ref{tab:cpio_options}, in cui si sono tralasciate le tre opzioni
principali per selezionare le modalità di operazione; al solito l'elenco
completo delle opzioni è disponibile nella pagina di manuale accessibile con
\texttt{man cpio}, anche se la documentazione è mantenuta principalmente nella
pagina info accessibile con \texttt{info cpio}.

%%
%% ### OBSOLETE BEGIN ###
%% Materiale obsoleto per dump e restore
%%
\ifx\obsoletesection\undefined

\relax
\else
\subsection{I comandi \texttt{dump} e \texttt{restore}}
\label{sec:dump_restore}

I comandi \texttt{tar} e \texttt{cpio} illustrati in precedenza vengono usati
per archiviare liste di file o directory sulla base di quanto specificato al
comando, per i backup esistono però anche dei comandi, come \texttt{dump} e
\texttt{restore}m che permettono di effettuare l'archiviazione a livello di un
intero filesystem.

Il limite di un programma come \index{comando!\texttt{dump}} \texttt{dump} è
che questo funziona solo per un filesystem che ne supporti le operazioni
salvando le informazioni necessarie.  Questo nel caso di Linux è vero solo per
il filesystem \textsl{ext2} e la sua estensione \textit{journalled},
\textsl{ext3}. Inoltre per poter utilizzare questa funzionalità occorre anche
montare opportunamente il filesystem, e come vedremo in
sez.~\ref{sec:file_disk_management}, per questo il file \texttt{/etc/fstab}
prevede un campo apposito, il quinto, che deve essere inizializzato
opportunamente ad un valore non nullo.

Una volta abilitato il supporto per il \textit{dump} del filesystem tramite
\texttt{fstab} effettuando operazioni di backup dello stesso tramite
\texttt{dump} saranno salvate le informazioni necessarie a ricostruire quali
file sono stati cambiati da un backup all'altro, così da permettere dei backup
incrementali. Il funzionamento del programma prevede la possibilità 10 diversi
livelli di \textit{dump}, numerati da 0 a 9, da specificare con le opzioni
omonime (cioè \texttt{-0}, \texttt{-1}, ...  \texttt{-9}), e se non viene
specificato nulla viene usato il livello 9.

Il livello 0 indica un backup completo, in cui si sono salvati tutti i file, e
stabilisce un punto di partenza per tutti gli altri livelli. Un livello
superiore richiede il salvataggio di tutti i file che sono cambiati
dall'ultimo backup effettuato con un livello inferiore. Questo significa che un
backup di livello 9 salverà sempre solo i file modificati dopo l'ultimo backup
precedente.

Quindi per fare un esempio,\footnote{si suppone che prima si sia partiti con
  un dump di livello 0, un passaggio iniziale infatti è sempre necessario.} se
si esegue un backup con livello 2 seguito da uno di livello 4 si avranno in
quest'ultimo solo i file cambiati dal momento in cui si è eseguito il
precedente backup di livello 2; se poi si eseguisse un dump di livello 3
sarebbero salvati di nuovo tutti i file modificati dopo il backup di livello 2
(e il livello 4 sarebbe ignorato), se al posto del dump di livello 3 se ne
fosse fatto uno di livello 5 invece si sarebbero salvati solo i file
modificati dopo il backup di livello 4.

Questo permette di poter eseguire i backup incrementali in maniera efficiente
per ridurre al minimo sia il tempo di recupero che il numero di supporti
utilizzati. Una possibile strategia di backup è quella riportata nella pagina
di manuale, in cui si fanno backup incrementali giornalieri, usando un insieme
di supporti da ruotare settimanalmente, usando un algoritmo di tipo
\textsl{torre di Hanoi} modificato.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-D} & permette di cambiare il file su cui viene mantenuta
                  l'informazione relativa ai precedenti backup (completi o
                  incrementali) che di solito è \texttt{/var/lib/dumpdates}.\\
    \texttt{-e} & esclude dal backup una lista di \textit{inode} (vedi
                  sez.~\ref{sec:struct_file_vfs}) passati per numero.\\
    \texttt{-E} & esclude una lista di \textit{inode} elencati nel file
                  specificato come parametro.\\
    \texttt{-f} & scrive il backup sul file passato come parametro, si possono
                  specificare più file separandoli con virgole, e saranno
                  considerati come volumi successivi. \\
    \texttt{-L} & usa la stringa passata come parametro come etichetta del 
                  backup. \\
    \texttt{-M} & abilita il salvataggio multivolume (in cui si usa
                  \texttt{-f} per specificare più di un volume di backup).\\
    \texttt{-u} & aggiorna il file \texttt{/var/lib/dumpdates} che contiene la
                  tabella in cui sono scritti i filesystem per i quali cui
                  sono stati effettuati i backup, e le rispettive date ed il
                  livello. \\
    \texttt{-v} & aumenta la \textsl{prolissità} del comando facendogli
                  stampare a video più informazioni riguardo le operazioni
                  correnti. \\
    \hline
  \end{tabular}
  \caption{Principali opzioni del comando \texttt{dump}.}
  \label{tab:dump_options}
\end{table}

A parte l'opzione che ne specifica il livello il comando richiede la presenza
dell'opzione \texttt{-f} seguita da un parametro che indica il file su cui
effettuare il backup (in genere si usano le unità a nastri, ma si può
specificare un file ordinario o usare \texttt{-} per indicare lo
\textit{standard output}), e prende come argomento il \textit{mount point} del
filesystem di cui si vuole eseguire il backup. In realtà si può anche
specificare una directory contenente i file che si vogliono archiviare e non
un \textit{mount point}, in questo caso però sono consentiti solo backup
completi di livello 0 e tutto il contenuto della directory deve risiedere
nello stesso filesystem.  Oltre quelle citate \texttt{dump} prende numerose
altre opzioni, molte delle quali sono relative alla gestione dei nastri su cui
usualmente vengono salvati i backup. Si sono riportate le principali in
tab.~\ref{tab:dump_options}, per l'elenco completo si può al solito fare
riferimento alla pagina di manuale.

Il comando che permette di recuperare i dati archiviati con \texttt{dump} è
\index{comando!\texttt{restore}} \texttt{restore}, che esegue esattamente il
compito inverso, e come \texttt{dump} usa l'opzione \texttt{-f} per indicare
il file (ordinario o di dispositivo) da cui recuperare i dati da ripristinare.
Il comando inoltre prevede la necessaria presenza di una serie di opzioni che
ne indicano la modalità di operazione.  Le principali sono \texttt{-C} che
effettua un confronto fra i file passati come argomento e quelli sul backup,
\texttt{-i} che porta in modalità interattiva (dove possono essere dati una
serie di comandi, descritti nella pagina di manuale), \texttt{-r} che permette
di ricostruire un intero filesystem da zero, \texttt{-t} che verifica se i
file passati come argomento sono nel backup o stampa a video il contenuto
integrale dello stesso se invocato senza argomenti, e \texttt{-x} che effettua
il ripristino dal contenuto dell'archivio: di una directory, se questa viene
passata come argomento, o di tutto l'archivio se non vengono passati
argomenti.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato}\\
    \hline
    \hline
    \texttt{-f} & indica il file in cui è stato memorizzato il backup.\\
    \texttt{-C} & esegue un confronto fra i file presenti nel filesystem e
                  quelli nel backup.\\
    \texttt{-i} & attiva la modalità interattiva.\\
    \texttt{-r} & ricostruisce un intero filesystem da zero.\\
    \texttt{-t} & presenta un elenco di file nel backup.\\
    \texttt{-x} & estrae una directory dal backup (o tutto il contenuto).\\
    \texttt{-h} & estrae il contenuto di una directory, e non di quelle in
                  essa contenute.\\
    \texttt{-M} & abilita il ripristino da un archivio multivolume.\\
    \texttt{-v} & stampa una maggiore quantità di informazione durante le
                  operazioni.\\
    \hline
  \end{tabular}
  \caption{Principali opzioni del comando \texttt{restore}.}
  \label{tab:restore_options}
\end{table}

Come \texttt{dump} anche \texttt{restore} prevede numerose opzioni, parecchie
delle quali servono a controllare proprietà relative all'uso dei nastri. Oltre
a quelle brevemente spiegate in precedenza si sono riportate in
tab.~\ref{tab:restore_options} le più rilevanti; al solito tutti i dettagli e
l'elenco completo delle opzioni (e dei comandi disponibili in modalità
interattiva) sono riportati nella pagina di manuale.

%%
%% ### OBSOLETE END ###
%% Materiale obsoleto per dump e restore
%%
\fi


\subsection{Altri comandi per il backup}
\label{sec:backup_misc_command}

Si sono raccolti in quest'ultima sezione alcuni comandi specialistici
utilizzati per effettuare delle copie di dati che risultano di un certo
interesse quando si devono eseguire dei backup, si tratta comunque di diverse
modalità per effettuare dei backup completi, realizzati con la creazione di
una copia di sicurezza dei dati che interessano. Se infatti è sempre possibile
usare il semplice \texttt{cp} per copiare dei dati (in genere con l'opzione
\texttt{-a} se si vogliono preservare anche le proprietà dei file e copiare
intere directory) esistono alcune esigenze specifiche che vengono coperte in
maniera più efficace ricorrendo ad altri comandi.

Il primo di questi comandi è \index{comando!\texttt{dd}} \texttt{dd} che viene
normalmente utilizzato quando si devono effettuare delle copie del contenuto
di interi dispositivi (dischi, floppy, chiavette USB ed anche CDROM). La
principale differenza di \texttt{dd} rispetto a \texttt{cp} è che questo è
nato, ed è presente fino dalle prime versioni di Unix, per effettuare delle
copie a basso livello dei dati presenti sui dispositivi a blocchi, e consente
di eseguire letture e scritture con buffer dati di dimensioni precise, in modo
che queste corrispondano alle dimensioni dei blocchi dei dispositivi su cui va
ad operare.

Dato che, come illustrato in sez.~\ref{sec:struct_file_vfs}, nei sistemi
unix-like ``\textsl{tutto è un file}'', per copiare i dati di un dispositivo
si potrebbero comunque usare anche comandi ordinari come \texttt{cp},
\texttt{dd} fornisce però un grado di controllo molto maggiore.  Inoltre il
programma consente di specificare quanti dati copiare, sia in termini di
numero di byte che di blocchi che di punto di partenza della copia, ed è per
questo molto utile quando si devono effettuare copie di parti specifiche di un
disco, come il \textit{Master Boot Record} (vedi sez.~\ref{sec:partitioning}).

Date le sue origini agli albori di Unix il comando ha una sintassi abbastanza
peculiare, che non usa le normali opzioni, e prevede invece che tutti gli
argomenti siano passati in forma di assegnazione (con il carattere
``\texttt{=}'') di valori ad altrettanti operatori che ne controllano il
comportamento. Se non si specificano argomenti il comando legge dallo
\textit{standard input} e scrive sullo \textit{standard output}, ma usato così
non è di grande utilità.

Per questo motivo il file da cui leggere e quello su cui scrivere vengono in
genere indicati esplicitamente con gli operatori \texttt{if} ed \texttt{of},
per cui un'invocazione tipica del comando, con il quale è ad esempio possibile
effettuare una copia fisica del contenuto di una chiavetta USB, sarà qualcosa
del tipo:\footnote{il file di dispositivo potrebbe anche essere un altro, a
  seconda della presenza o meno di altri dischi (vedi
  sez.~\ref{sec:disk_structure}), ovviamente si dovranno avere gli opportuni
  permessi di accesso al dispositivo, che normalmente sono disponibili solo
  all'amministratore.}
\begin{Example}
dd if=/dev/sdb of=usbkey.img
\end{Example}
ed invertendo i valori dei due operatori si potrà effettuare il ripristino
dalla copia. Si faccia comunque molta attenzione quando si va a scrivere su un
dispositivo, perché il comando non chiede nessuna conferma, ed in caso di
errore si rischia di distruggere totalmente il contenuto di un disco.

In questo modo il comando usa il valore di default di 512 byte per la
dimensione dei blocchi; questa si può impostare con l'operatore \texttt{bs} a
cui assegnare sia un semplice valore numerico (che specifica la dimensione in
byte), che un valore con un prefisso che consente di indicare kilobyte,
megabyte, ecc. Il comando supporta prefissi diversi per indicare sia i
kilobyte metrici (1000 byte, con \texttt{Kb}) che gli usuali kilobyte
``\textit{informatici}'' (1024 byte, con \texttt{K}); lo stesso vale per le
altre dimensioni (con \texttt{M}, \texttt{G}, ecc.), per i dettagli si
consulti la pagina di manuale.

Altri operatori importanti sono \texttt{count}, che consente di indicare
quanti blocchi copiare, \texttt{skip} che consente di indicare un numero di
blocchi dall'inizio del file da saltare nella lettura, e \texttt{seek} che
esegue la stessa operazione sul file su cui scrivere. In questo modo è
possibile fare eseguire a \texttt{dd} operazioni di copia di sezioni
specifiche di un file su altre sezioni specifiche di un altro file. Si sono
riportati i principali operatori in tab.~\ref{tab:dd_operand}, per l'elenco
completo, che comprende anche quelli che consentono di effettuare al volo
alcune conversioni di dati, si consulti al solito la pagina di manuale. 

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Operatore} & \textbf{Significato}\\
    \hline
    \hline
    \texttt{if}   & file di ingresso da cui leggere i dati.\\
    \texttt{of}   & file di uscita su cui scrivere i dati.\\
    \texttt{count}& numero di blocchi da leggere/scrivere.\\
    \texttt{seek} & numero di blocchi da saltare nel file di uscita prima di
                    iniziare la scrittura.\\
    \texttt{skip} & numero di blocchi da saltare nel file di ingresso prima di
                    iniziare la lettura.\\
    \texttt{bs}   & dimensione di un blocco di dati (512 byte di default).\\
    \texttt{obs}  & dimensione di un blocco di dati per la lettura.\\
    \texttt{ibs}  & dimensione di un blocco di dati per la scrittura.\\
    \hline
  \end{tabular}
  \caption{Principali operatori del comando \texttt{dd}.}
  \label{tab:dd_operand}
\end{table}

Si tenga presente però che per effettuare correttamente la copia a basso
livello del contenuto di un dispositivo a scopo di backup occorre che il
filesystem presente nel dispositivo che si va a copiare non sia montato, in
caso contrario infatti i dati saranno inconsistenti.\footnote{se il filesystem
  è montato il kernel lo aggiornerà in maniera autonoma, e non c'è nessuna
  garanzia sulla coerenza dei dati che potranno essere visti da \texttt{dd}
  nel momento in cui il programma li legge.}  È per questo motivo che per
effettuare un backup a livello di dispositivo normalmente si usano comandi
specifici (come \texttt{dump} e \texttt{restore} per \textit{ext4}), se però
il dispositivo non è montato o è montato in sola lettura (vedi
sez.~\ref{sec:file_disk_management}) la coerenza è assicurata e si otterrà una
copia corretta.

Un secondo comando molto utile per la realizzazione di backup è
\index{comando!\texttt{rsync}} \texttt{rsync}. Il comando, come indica il
nome, nasce per mantenere sincronizzato il contenuto di singoli file o intere
directory sia in locale che in remoto. Rispetto all'uso di comandi come
\texttt{tar} e \texttt{cp}, oltre alla capacità di lavorare via rete, ha il
vantaggio di essere in grado di mantenere al minimo la quantità di dati
trasferita. Il programma infatti funziona operando soltanto sui file che sono
stati modificati, e trasmettendo, grazie un algoritmo sofisticato che gli
consente di determinarle, soltanto le differenze presenti fra le due versioni,
e non l'intero contenuto.

Per questo motivo \texttt{rsync} è molto utile quando si deve eseguire una
copia di dati via rete o si ha a che fare con un mezzo lento come ad esempio
un disco USB. Se infatti si dispone già di una versione precedente di quanto
si vuole copiare, il comando trasferirà solo le differenze consentendo una
operazione di copia molto più veloce.

La sintassi di base del comando è analoga a quella di \texttt{cp} e prevede
come argomenti una o più sorgenti ed una destinazione; qualora ci siano più
sorgenti (vale a dire più di due argomenti) la destinazione deve essere una
directory. Il comando può essere usato anche con un solo argomento, nel qual
caso fornisce la lista dei file presenti nella sorgente. Se usato localmente
sorgenti e destinazione non sono altro che dei pathname, ma il comando
consente di utilizzare una sorgente o una destinazione remota,\footnote{non
  entriamo qui nei dettagli delle modalità del trasferimento via rete, se non
  per dire che normalmente questo avviene attraverso l'uso di SSH, che
  tratteremo in sez.~\ref{sec:net_ssh}.} nel qual caso la forma generica
dell'argomento sarà qualcosa del tipo:
\begin{Example}
user@machinename:/path/to/dest_or_src
\end{Example}
la sintassi del comando però richiede che quando la sorgente è remota questa
debba essere unica e la destinazione debba essere locale.

L'uso più comune di \texttt{rsync} è quello che prevede due directory come
argomenti, per sincronizzare il contenuto della prima sulla seconda.  Si tenga
presente inoltre che quando si specifica come sorgente una directory il
comando si comporta diversamente a seconda che questa sia indicata o meno con
una ``\texttt{/}'' finale, nel primo caso infatti nella destinazione viene
copiato solo il contenuto della directory, mentre nel secondo caso anche la
directory stessa viene copiata all'interno della directory di destinazione. In
entrambi i casi gli attributi della directory sorgente vengono comunque
trasferiti sulla destinazione.

In generale quando lo si usa per eseguire copie il comando viene invocato con
l'opzione \texttt{-a}, che consente di preservare link simbolici, file di
dispositivo e tutti gli attributi (permessi, proprietari, tempi) di file e
directory. Una seconda opzione comune, usata soprattutto per i trasferimenti
via rete, è \texttt{-z} che attiva la compressione dei dati, mentre con
\texttt{-v} si aumenta la prolissità del comando. Infine con \texttt{-u} si
richiede al comando di non sincronizzare i file che risultano più recenti,
come tempo di ultima modifica, nella destinazione.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-a} & effettua un trasferimento in modalità archivio, equivalente
                  a \texttt{-rlptgoD}.\\
    \texttt{-A} & preserva le ACL.\\
    \texttt{-e} & specifica la shell remota da usare.\footnotemark\\
    \texttt{-D} & preserva file speciali e di dispositivo.\\
    \texttt{-g} & preserva il gruppo proprietario.\\
    \texttt{-H} & riconosce gli \textit{hard link} e li
                  mantiene nella destinazione (dispendiosa).\\
    \texttt{-l} & copia i link simbolici come tali.\\
    \texttt{-o} & preserva l'utente proprietario.\\
    \texttt{-p} & preserva i permessi.\\
    \texttt{-r} & effettua una copia ricorsiva del contenuto della
                  sorgente sulla destinazione.\\
    \texttt{-t} & preserva i tempi.\\
    \texttt{-u} & non esegue la sincronizzazione se a destinazione esiste una
                  versione più recente.\\
    \texttt{-v} & aumenta la prolissità.\\
    \texttt{-X} & preserva gli attributi estesi.\\
    \texttt{-z} & comprime i dati durante il trasferimento.\\
    \texttt{-{}-exclude}& esclude un insieme di file dalla copia.\\
    \texttt{-{}-delete} & cancella sulla destinazione quanto non presente
                  nella sorgente.\\
    \hline
  \end{tabular}
  \caption{Principali opzioni del comando \texttt{rsync}.}
  \label{tab:rsync_options}
\end{table}

\footnotetext{il default è \texttt{rsh}, che sui sistemi recenti è un alias a
  \texttt{ssh}, ma l'opzione consente di specificare l'intera riga di comando
  da invocare sull'altro lato della connessione.}

Un elenco delle altre opzioni più significative è riportato in
tab.~\ref{tab:rsync_options}, ed al solito per una documentazione più completa
si può far riferimento alla pagina di manuale. Vale però la pena evidenziare
due opzioni utilizzabili solo in forma estesa; con \texttt{-{}-delete} si può
richiedere la cancellazione nella destinazione dei file non presenti nella
sorgente (il default è lasciarli) mentre con \texttt{-{}-exclude} si può
indicare un insieme di file da non trasferire, questa opzione prende come
argomento una espressione analoga a quelle del \textit{filename globbing} la
cui sintassi è supportata integralmente, insieme ad alcune estensioni
descritte in dettaglio nella pagina di manuale.



\subsection{La gestione dei nastri}
\label{sec:tape_management}

Come accennato in sez.~\ref{sec:adv_backup_criteria} uno dei supporti più
utilizzati per lo stoccaggio dei dati di backup è quello dei
nastri. Trattandosi di dispositivi non molto comuni, prima di trattare i
comandi che si utilizzano per la loro gestione, conviene illustrarne
brevemente il funzionamento. 

Come già accennato in sez.~\ref{sec:tar_cpio} i nastri (almeno quelli
attualmente in uso) sono acceduti in maniera quasi esclusiva attraverso il
protocollo SCSI, che prevede delle specifiche estensioni a loro dedicate.  Le
tecnologie di basso livello sono state le più varie e hanno visto diverse
evoluzioni, ma oggi in genere vengono utilizzati (almeno nell'ambito dei
salvataggi dei dati di backup) i cosiddetti LTO (\textit{Linear Tape-Open}),
una standardizzazione del formato dei nastri iniziata nel 2000 che ha visto il
susseguirsi di diverse evoluzioni con capacità e velocità
crescenti.\footnote{una buona panoramica sull'argomento è disponibile su
  \url{http://en.wikipedia.org/wiki/Linear_Tape-Open}.}  Si è passati così dai
100G utilizzati dalla prima versione (LTO-1, ma più nota come Ultrium) ai
2.5Tb della più recente LTO-6. Oggi le versioni più ancora usate in maniera
sostanziale sono LTO-3 (450Gb), LTO-4 (800Gb) ed LTO-5 (1.5Tb).

Benché esistano anche altre teconologie, noi prenderemo in considerazione solo
nastri SCSI; il supporto fornito dal kernel consente di compiere delle
operazioni di controllo, che esamineremo più avanti, mentre li si leggono e
scrivono operando direttamente sui relativi file di dispositivo. Come
accennato questi sono nella forma \texttt{/dev/st\textsl{N}} e
\texttt{/dev/nst\textsl{N}}, dove \texttt{\textsl{N}} è un numero progressivo
che parte da 0 e che viene assegnato dal kernel quando riconosce eventuali
``\textit{drive}'' multipli aggangiati alla macchina.

La differenza fra i due nomi è dovuta al fatto che nel primo caso tutte le
volte che il file di dispositivo viene chiuso (dopo una lettura o una
scrittura) il nastro viene riavvolto fino all'inizio (si parla di
\textit{rewinding}), mentre nel secondo caso il nastro non viene riavvolto
(\textit{non rewinding}). La necessità di questa differenza emerge una volta
che siano chiare le modalità con cui i dati vengono salvati su un nastro. I
nastri infatti hanno delle caratteristiche specifiche, che li distinguono
dagli altri dispositivi su cui è possibile salvare dati, come dischi o CDROM,
la più rilevante delle quali è che sia lettura che scrittura possono essere
esclusivamente seriali, per cui si possono salvare solo file e non esistono
directory.

\begin{figure}[!htb]
\centering
\includegraphics[scale=0.5]{images/tape-arch}
\caption{La struttura del salvataggio dei file su nastro.}
\label{fig:tape_architecture}
\end{figure}

La struttura dei dati su un nastro è mostrata
fig.~\ref{fig:tape_architecture}, all'inizio del nastro è posto il primo file
che si è scritto, i successivi sono disponibili e separati da l'uno dall'altro
da un opportuno separatore chiamato \textit{file mark}. Non esiste un
filesystem ed i file non hanno nome e sono numerati progressivamente a partire
da zero.

Tutte le volte che si scrive un file, utilizzando il dispositivo \textit{non
  rewinding}, la posizione della testina resta posizionato in coda al file
appena scritto. Se si scrive un altro file sul nastro, prima viene inserito un
\textit{file mark} e poi vengono scritti i dati file e via così. Se invece si
legge un file, la posizione resta sulla coda del primo file, e se si vuole
leggere il file successivo però non si può leggere direttamente, proprio
perché non si è all'inizio del file successivo, occorre far spostare la
testina dopo il \textit{file mark}.

Il comando per gestire i nastri è \index{comando!\texttt{mt}} \texttt{mt} (da
\textit{\textbf{m}agnetic \textbf{t}ape}); il comando richiede che si indichi
il nastro su cui operare con l'opzione \texttt{-f} (o \texttt{-t}) o con la
variabile di ambiente \texttt{TAPE}, che è il riferimento usato da tutti i
programmi che usano i nastri. Se non si indica nulla viene usato
\texttt{/dev/tape} che può essere usato creando un link simbolico al
dispositivo da usare di default.

Del comando esistono varie versioni, si verifichi che si sia installata la
versione che supporta il driver dei nastri SCSI di Linux (su Debian il
pacchetto è \texttt{mt-st}) che supporta l'opzione \texttt{-h} che elenca le
operazioni disponibili. Del comando infatti esiste anche una versione
generica che supporta solo le operazioni più elementari, come \texttt{status},
\texttt{rewind}, \texttt{erase} o \texttt{eject} che rispettivamente stampano
lo stato del nastro, lo riavvolgono, lo cancellano, e lo riavvolgono ed
espellono.

Il comando vuole come primo argomento il nome dell'operazione da eseguire
seguito da un valore di conteggio, che in genere è un numero intero, che può
essere espresso, a seconda dell'operazione scelta, anche con i suffissi
\texttt{k}, \texttt{M} o \texttt{G} come potenze progressive di 1024,
alternativamente si possono indicare, con i relativi comandi, le opzioni di
gestione del nastro. Si sono riportate le principali operazioni in
tab.~\ref{tab:mt_operations}, mantenendo quelle generali nella prima parte
della tabella, per l'elenco completo si consulti la pagina di manuale.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Operazione} & \textbf{Significato}\\
    \hline
    \hline
    \texttt{eject} & riavvolge ed espelle il nastro.\\
    \texttt{erase} & cancella il nastro.\\
    \texttt{rewind} & riavvolge il nastro.\\
    \texttt{status} & stampa lo stato del nastro.\\
    \texttt{fsf \textsl{count}} & si sposta in avanti per
                                  \texttt{\textsl{count}} \textit{file mark}.\\ 
    \texttt{bsf \textsl{count}} & torna indietro di \texttt{\textsl{count}}
                                  \textit{file mark}.\\
    \hline
    \texttt{stclearopt \textsl{opt}} & rimuove l'opzione indicata per il
                                       nastro.\\ 
    \texttt{stsetopt \textsl{opt}} & imposta l'opzione indicata per il
                                     nastro.\\ 
    \texttt{setblk \textsl{count}} & imposta le dimensioni di un blocco a
                                     \texttt{\textsl{count}} byte.\\
    \hline
  \end{tabular}
  \caption{Principali operazioni del comando \texttt{mt}.}
  \label{tab:mt_operations}
\end{table}

L'operazione più utilizzata è probabilmente \texttt{status}, che consente di
ottenere lo stato di un dispositivo, e che riporta le informazioni, oltre alla
presenza o meno del nastro, che consentono anche di orientarsi sulla posizione
in cui esso si trova. Ad esempio se il nastro è stato appena riavviato si avrà
qualcosa del tipo:\footnote{se ci si sposta sul nastro si abbia cura di usare
  sempre il dispositivo \texttt{/dev/nst0}, usare \texttt{/dev/st0} ne
  comporterebbe il riavvolgimento rendendo inutili varie operazioni.}
\begin{Console}
root@taper:~# \textbf{mt -f /dev/nst0 status}
SCSI 2 tape drive:
File number=0, block number=0, partition=0.
Tape block size 0 bytes. Density code 0x58 (no translation).
Soft error count since last status=0
General status bits on (41010000):
 BOT ONLINE IM_REP_EN
\end{Console}
ed il risultato ci mostra, nella seconda riga, che il nastro è posizionato sul
primo blocco (\texttt{block number=0}) del primo file (\texttt{File
  number=0}). La riga successiva ci dice la dimensione dei blocchi dei file
(il valore nullo indica la cosiddetta dimensione variabile) ed il codice che
indica il tipo di nastro (nel caso un LTO-5). Se a questo punto salviamo
qualcosa sul nastro, ad esempio eseguendo in comando come \texttt{tar -cvf
  /dev/nst0 corso}, rieseguendo il precedente comando otterremo:
\begin{Console}
...
File number=1, block number=0, partition=0.
...
\end{Console}
con il nastro posizionato sul file successivo. Se a questo punto creiamo un
secondo archivio con \texttt{tar -cvf /dev/nst0 webservices}, ripetendo di
nuovo il comando, otterremo:
\begin{Console}
...
File number=2, block number=0, partition=0.
...
\end{Console}
se a questo punto si riavvolge il nastro con \texttt{mt rewind}, si potrà
rileggere il primo archivio con:
\begin{Console}
root@taper:~# \textbf{tar -tvf /dev/nst0}
drwxr-xr-x root/root         0 2015-05-21 16:21 corso/
drwxr-xr-x root/root         0 2015-05-21 16:20 corso/images/
-rw-r--r-- root/root     44495 2015-05-21 16:08 corso/images/aptitude.png
...
\end{Console}
ma una volta controllata la posizione sul nastro si avrà:
\begin{Console}
root@taper:~# \textbf{mt -f /dev/nst0 status}
SCSI 2 tape drive:
File number=0, block number=281, partition=0.
...
\end{Console}
che ci mostra come in questo caso si sia posizionati alla fine del primo file
(si noti il \textit{block number}) cioè prima del \textit{file mark}
illustrato in fig.~\ref{fig:tape_architecture}.  Se a questo punto si volesse
leggere il secondo archivio salvato in precedenza ripetendo il comando
\texttt{tar} si otterrebbe un errore, non essendo ancora posizionati
all'inizio del secondo file sul nastro.

Per modificare il posizionamento sul nastro, in modo da potersi posizionare
con precisione all'inizio di un file, \texttt{mt} fornisce altre due
operazioni: \texttt{fsf} (\textit{forward space file}) che porta all'inizio
del file successivo (più precisamente alla prima fine di \textit{file mark}
incontrata andando avanti sul nastro), e \texttt{bsf} (\textit{backward space
  file}) che riporta alla fine del file precedente (più precisamente al primo
inizio di \textit{file mark} incontrato andando indietro sul nastro).
Entrambe le operazioni supportano l'indicazione di un conteggio che consente
di specificare di quanti \textit{file mark} spostarsi avanti o indietro. Nel
nostro esempio per potere rieseguire \texttt{tar} ed ottenere il contenuto
della directory \texttt{webservices}, dovremmo allora eseguire un \texttt{fsf}
per posizionarsi all'inizio del file successivo, ottenendo:
\begin{Console}
root@taper:~# \textbf{mt -f /dev/nst0 fsf}
root@taper:~# \textbf{mt -f /dev/nst0 status}
SCSI 2 tape drive:
File number=1, block number=0, partition=0.
...
\end{Console}
ed a questo punto si potrebbe ripetere l'estrazione con successo. 

Per tornare indietro nella sequenza dei file occorre usare \texttt{bsf}, ma in
tal caso come accennato si torna sempre in coda al file precedente. Questo
significa che per trovarsi effettivamente in testa al file precedente
occorrerebbe eseguire due \texttt{bsf} e poi un \texttt{fsf}. Questo però non
vale per il primo file del nastro, per cui non c'è un \textit{file mark}
iniziale, per cui la procedura comporterebbe prima un errore con \texttt{bsf}
e poi il ritorno al secondo file col successivo \texttt{fsf}.  Per questo
motivo se si vuole essere sicuri di essersi posizionati all'inizio
dell'$n$-simo file in qualunque condizione, l'unica possibilità è eseguire la
sequenza \texttt{mt rewind; mt fsf \textsl{n}} che ha però l'inconveniente,
riavvolgendo sempre il nastro, di essere più lenta.

Un'altra caratteristica specifica dei nastri è quella di operare con scritture
effettuate sempre in blocchi di dimensione fissa, che viene riportata nei
risultati di \texttt{mt status} dalla riga ``\texttt{Tape block
  size}''. Questo comporta una complicazione nelle operazioni di lettura e
scrittura di cui occorre tenere conto, perché eseguire una scrittura di
dimensione superiore a quella dei blocchi del nastro significa perdere i dati
che eccedono quest'ultima, mentre usare scritture di dimensioni inferiori
significa sprecare spazio, dato che viene comunque scritto un blocco. Questo
comportamento richiede che i programmi di scrittura siano in grado di
specificare le dimensioni dei blocchi di dati che vengono scritti; inoltre se
si cerca di rileggere un file usando una dimensione dei blocchi che non
corrisponde a quella usata per scriverlo si otterrà un errore, non
particolamente esplicativo, relativo all'impossibilità di allocare la memoria.

Un tempo ciascun tipo di nastro aveva una sua specifica dimensione, fissa, dei
blocchi, e si doveva usare quella; oggi ormai quasi tutti (gli LTO tutti)
supportano i blocchi di dimensione variabile, indicata da un valore nullo per
``\texttt{Tape block size}''.  Quando si imposta la dimensione variabile si
possono effettuare scritture usando un numero arbitrario di byte,\footnote{per
  essere precisi si può usare una dimensione qualunque per il buffer dati dei
  da scrivere usato nella chiamata alla \textit{system call} \texttt{write},
  senza essere più vincolati a fare riferimento al valore supportato dal
  nastro.} e questi verranno considerati un ``blocco'' per cui non si
perderanno mai dati in scrittura o sprecherà spazio. Ma resta il fatto che sul
nastro i dati verranno comunque registrati come un blocco, e come tale
dovranno essere riletti; il risultato è che se la scrittura può avere blocchi
di dimensioni arbitrarie la lettura no, e deve essere effettuata usando
blocchi della stessa dimensione usata in scrittura.

Ogni programma usa una sua dimensione di default per le scritture, ad esempio
con \texttt{tar} la dimensione è di 10Kb (il \textit{blocking factor} di
default, impostabile con l'opzione \texttt{-b}, è 20), mentre con \texttt{dd}
è di 512 byte, per cui cercando di rileggere un archivio \texttt{.tar} salvato
su un nastro con \texttt{dd} si otterrebbe un errore, a meno di non impostare
una dimensione corretta dei blocchi (nel caso occorrerebbe indicare
\texttt{bs=10k}). 

L'uso della dimensione variabile ha il vantaggio di non richiedere la
conoscenza dei blocchi sul nastro, ma esegue letture e scritture sempre un
blocco alla volta, e questo può avere un impatto negativo sulle prestazioni,
infatti se la dimensione del blocco è nota il kernel è in grado di effettuare
letture di più blocchi in un solo colpo usando il buffer dati associato a
ciascun nastro (la cui dimensione ordinaria è 32kb). Questo però avviene
soltanto se si imposta con l'operazione \texttt{setblk} la dimensione dei
blocchi del nastro; in genere i sistemi di backup (come Amanda o Bacula) che
operano con i nastri effettuano questo tipo di ottimizzazione per conto
proprio.



\section{La gestione dei pacchetti software}
\label{sec:adv_package_admin}

Affronteremo in questa sezione le varie modalità in cui un amministratore può
installare e rimuovere software dal sistema, in particolare esaminando i
diversi sistemi di gestione dei pacchetti messi a disposizione dalle varie
distribuzioni che permettono di tenere traccia, aggiornare e rimuovere tutto
quello che si è installato nella propria macchina.


\subsection{L'installazione diretta dai sorgenti}
\label{sec:install_tarball}

Una delle caratteristiche costitutive del software libero è la disponibilità
del sorgente dei programmi, pertanto è sempre possibile effettuare una
\textsl{installazione diretta} a partire dal codice che viene distribuito
direttamente dagli sviluppatori. In generale questo può avvenire nelle
modalità più disparate, e dipende anzitutto dal linguaggio in cui lo stesso
software viene scritto.  Tratteremo in questa sezione il caso più comune, in
cui i programmi da installare devono essere prima compilati, qualora il
software sia stato scritto in un linguaggio interpretato in genere tutto
quello che servirà sarà semplicemente installare i file che lo compongono in
maniera opportuna nella propria macchina.

Nella maggior parte dei casi il software viene distribuito in forma sorgente
in degli archivi compressi chiamati gergalmente ``\textit{tarball}'', in
quanto creati con il programma \texttt{tar}, trattato in
sez.~\ref{sec:tar_cpio}. In genere gli archivi vengono pure compressi, per cui
di norma li si trovano distribuiti in file che usano l'estensione
\texttt{.tar.gz} (talvolta abbreviata in \texttt{tgz}, per l'uso di sistemi
obsoleti che hanno problemi coi nomi di file che hanno troppi caratteri
``\texttt{.}'' al loro interno) dato che il programma di compressione più
usato è \texttt{gzip}. Una alternativa abbastanza comune per gli archivi più
grandi è quella dell'uso di \texttt{bzip2}, o recentemente \texttt{xz}; nel
qual caso l'estensione usata è rispettivamente \texttt{.tar.bz2} o
\texttt{.tar.xz}.

Per installare un pacchetto dai sorgenti la prima cosa da fare è scaricare
l'archivio degli stessi dal sito di sviluppo: è consigliato usare, se ci sono,
degli eventuali \textit{mirror}, dato che questi di norma sono meno
\textsl{occupati} del sito originale, e probabilmente anche più
``\textsl{vicini}'' in termini di distanza sulla rete e quindi con una
maggiore velocità di accesso.

Una volta scaricato il pacchetto se ne può verificare il contenuto o
scompattarlo usando il comando \texttt{tar} usando la sintassi trattata in
sez.~\ref{sec:tar_cpio}. Ad esempio se il pacchetto è distribuito nel file
\texttt{pacchetto.tar.gz} lo si potrà decomprimere con il comando \texttt{tar
  -xvzf pacchetto.tar.gz}. In genere questo crea una directory identica a
quella che conteneva tutti i file necessari sulla macchina in cui è stato
creato l'archivio.  È pratica comune usare una directory con lo stesso nome
del pacchetto, a cui si suole aggiungere un numero di versione progressivo che
consenta di distinguere i vari rilasci.

A questo punto per l'installazione occorre eseguire le operazioni previste
allo scopo dagli sviluppatori. Queste possono risultare molto diverse da
pacchetto a pacchetto, ma in genere chiunque distribuisce software fornisce
anche le informazioni necessarie su come effettuare l'installazione. Di norma
queste vengono distribuite insieme ai sorgenti, ed è prassi comune trovarle nei
file \texttt{README} o \texttt{INSTALL}.

Si tenga presente comunque che installare un pacchetto dai sorgenti presenta
dei requisiti maggiori rispetto all'installazione di un pacchetto binario, in
quanto non basta copiare dei file nella loro destinazione finale. Infatti se
il codice deve essere compilato sono necessari una serie di strumenti che
tipicamente non vengono installati in macchine su cui non si fa sviluppo, come
compilatori, programmi per la costruzione dei binari, file di sviluppo delle
librerie. Anzi è buona norma di sicurezza non avere installati compilatori ed
altri tool di sviluppo su server di produzione, per rendere più complicata la
vita ad eventuali ``\textsl{intrusi}'' che volessero installare i
``\textsl{loro}''.

Inoltre molti programmi per funzionare possono necessitare di altri programmi
o, caso molto comune, fare uso di specifiche librerie di funzioni. Essendo
questi per lo più sviluppati in maniera indipendente, normalmente non vengono
distribuiti insieme ai sorgenti del programma, e quindi non è detto che siano
già presenti ed installati. Ci sono cioè quelle che tecnicamente vengono
chiamate \textsl{dipendenze}, che devono essere risolte prima di poter
procedere all'installazione.

Per cercare di semplificare la procedura di installazione dai sorgenti il
progetto GNU ha realizzato un insieme di programmi, chiamati
\itindex{autotools} \textit{autotools}, che consente di verificare che tutto
quello che serve per la costruzione del pacchetto sia presente. Se un progetto
usa gli \textit{autotools}, o se segue la procedura di installazione definita
da questi ultimi, tutto quello che c'è da fare è di entrare nella directory
dove si è scompattato il contenuto della \textit{tarball} ed eseguire la
sequenza di comandi:
\begin{Example}
./configure
make
make install
\end{Example}

Il primo comando, \texttt{./configure}, esegue uno script di shell fornito coi
sorgenti che verifica che nel sistema sia presente tutto quello che serve per
compilare il pacchetto. Questo è il punto più critico della procedura, in
quanto se manca qualcosa lo script si interromperà dicendo o che non ci sono i
vari programmi di compilazione e costruzione, o che non esiste il supporto per
una funzionalità necessaria al programma o che mancano i file di dichiarazione
relativi ad una certa libreria che serve al programma, o la libreria stessa.

Lo script \texttt{configure} fornito dagli \textit{autotools} prevede anche
che sia possibile controllare le modalità di compilazione attraverso una serie
di variabili di ambiente, riportate in tab.~\ref{tab:ldap_configure_vars}, che
permettono di modificare il compilatore e le relative opzioni. In generale lo
script è in grado di riconoscere automaticamente i valori ottimali per le
suddette variabili, e non è necessario utilizzarle.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|l|}
    \hline
    \textbf{Variabile} & \textbf{Utilizzo} \\
    \hline
    \hline
    \texttt{CC}      & specifica un altro compilatore.\\
    \texttt{CFLAGS}  & specifica opzioni di compilazione addizionali.\\
    \texttt{CPPFLAGS}& specifica opzioni addizionali per il preprocessore.\\
    \texttt{LDFLAGS} & specifica opzioni per il linker.\\
    \texttt{LIBS}    & specifica librerie addizionali.\\
    \hline
  \end{tabular}
  \caption{Le variabili di ambiente usate dallo script di configurazione degli
    \textit{Autotools}.}
  \label{tab:ldap_configure_vars}
\end{table}


Per effettuare una installazione dai sorgenti il requisito fondamentale è
ovviamente quello di avere installato il relativo compilatore.  Nei casi più
comuni i programmi sono scritti in linguaggi come il C o il C++ e allora è
sufficiente installare i programmi \texttt{gcc} e \texttt{g++} e tutto quanto
fa parte della \textit{GNU Compiler Collection} che oltre a questi due
compilatori contiene pure una serie di altri programmi accessori. In genere
questi programmi vengono forniti direttamente dalla propria distribuzione, e
si dovrà semplicemente installarli con le modalità previste da
quest'ultima.\footnote{nel caso di Debian si può installare in un colpo solo
  tutto il necessario alla compilazione di programmi di base richiedendo il
  meta-pacchetto \texttt{build-essential}.}

Un secondo programma essenziale per l'installazione dai sorgenti è
\index{comando!\texttt{make}} \texttt{make}, che, come dice il nome, viene
usato per automatizzare la \textsl{costruzione} dei binari a partire dai
sorgenti, consentendo di definire tutte le procedure necessarie per la
creazione dei file nella giusta sequenza, sulla base di una serie di ricette
contenute negli appositi \texttt{Makefile}. Il programma funziona eseguendo le
istruzioni che trova in un file con questo nome posto nella directory
corrente, è compito proprio dello script \texttt{configure} creare detto file
con i corretti contenuti.

Se si è installato tutto quello che è necessario alla compilazione, e si sono
risolte tutte le dipendenze da altro software o librerie, lo script
\texttt{configure} terminerà senza errori e si potrà passare al comando
successivo. In questa fase uno degli errori più comuni che si può presentare è
che, pur avendo installato il software e tutte le librerie necessarie, non
siano presenti i file di dichiarazione associati alla librerie, che sono
necessari al compilatore per poter accedere alle funzioni in esse definite
nella fase di compilazione.

Il problema è comune perché per un programma binario già compilato questi file
non sono necessari, e pertanto è normale che non siano installati anche se ci
sono le librerie corrispondenti.  Però essi vengono messi a disposizione da
tutte le distribuzioni come pacchetti con lo stesso nome di quello della
libreria a cui fanno riferimento, a cui viene aggiunto un \texttt{-dev} per
indicare che si tratta della parte necessaria allo sviluppo, servono infatti
non solo per compilare un programma per l'installazione, ma anche qualora si
volessero sviluppare programmi che utilizzano le corrispondenti librerie.  In
questo caso non c'è altro da fare che installare anche questi pacchetti di
sviluppo, rifacendosi di nuovo al meccanismo di gestione fornito dalla propria
distribuzione.

Una volta che \texttt{./configure} ha completato con successo le sue
operazioni si potrà eseguire il secondo comando nella sequenza, \texttt{make},
che esegue la costruzione dei binari. Questo in genere dà luogo ad una lunga
serie di messaggi da parte del compilatore, fino a quando le operazioni non
sono concluse.  Se qualcosa va storto in questa fase restano solo due strade,
si può scrivere un \textit{bug report} a chi ha creato il pacchetto (evitando
troppi accidenti e fornendo le righe in cui si è verificato l'errore) ed
aspettare una risposta o provare a correggere l'errore da soli, ma in
quest'ultimo caso dovrete essere un po' pratici di programmazione, nel qual
caso probabilmente potete evitare di leggere queste pagine. Come ultima
risorsa potete comunque provare a cercare sui motori di ricerca se qualcuno ha
già incontrato un problema simile al vostro e se ne è stata fornita una
qualche soluzione.

Una volta completata la compilazione con \texttt{make install} si dice allo
stesso programma di eseguire le istruzioni di installazione. Si tenga presente
che la procedura standard, seguendo le linee guida del \textit{Filesystem
  Hierarchy Standard} di sez.~\ref{sec:file_FHS}, prevede di installare i
pacchetti compilati dai sorgenti sotto \texttt{/usr/local/}, per cui per
poterli utilizzare occorre avere le directory di questa gerarchia secondaria
nel PATH della shell (vedi sez.~\ref{sec:shell_sintax}) e si deve essere in
grado di usare le eventuali librerie ivi installate dal pacchetto (secondo
quanto illustrato in sez.~\ref{sec:cfg_dyn_lib}).

Se si usa la versione di \texttt{configure} degli \textit{Autotools GNU} è
possibile cambiare questa directory passando allo script \texttt{./configure}
l'opzione \texttt{-{}-prefix} che prende come parametro il pathname della
directory dove si vuole che venga eseguita l'installazione.  Alternativamente,
per non dover rieseguire lo script di configurazione se ci si è dimenticati
l'opzione, si può modificare la variabile \texttt{PREFIX} definita nelle prime
righe del \texttt{Makefile} principale nella directory dei sorgenti. Si può
anche indicare una specifica directory per l'installazione dei binari con
l'opzione \texttt{-{}-exec-prefix}, il cui default è comunque usare il valore
indicato per \texttt{-{}-prefix}.

Si tenga presente che la procedura descritta vale solo se gli sviluppatori
hanno deciso di usare il sistema di costruzione e controllo fornito dagli
\textit{autotools} del progetto GNU. In generale non è detto che questo
avvenga, nel qual caso occorre rifarsi alle istruzioni lasciate dal
programmatore. Alternative possibili sono, per progetti non troppo complessi,
la semplice invocazione del comando \texttt{make} (e di un successivo
\texttt{make install}), o l'uso diretto del compilatore, ma questo in genere
solo in casi elementari.

Benché sia sempre possibile eseguire una installazione dai sorgenti, in una
pratica di buona amministrazione questo dovrebbe essere evitato il più
possibile anche quando, come avviene con la procedura appena illustrata, una
tale installazione non risulti neanche particolarmente complessa. Infatti a
parte i problemi preliminari relativi a dover sistemare a mano tutte le
dipendenze di un pacchetto, o al tempo impiegato per eseguire la compilazione
dei programmi,\footnote{questo per pacchetti piccoli può anche essere
  trascurabile, ma per pacchetti importanti come il server X può essere, a
  seconda della potenza della macchina, dell'ordine delle ore o dei giorni.}
il problema maggiore resta la manutenzione di quanto si è installato, a causa
delle difficoltà relative all'aggiornamento e alla eventuale rimozione.

Infatti se installare è facile, disinstallare è molto più problematico. Alcuni
pacchetti (una minoranza purtroppo) forniscono uno speciale
\textsl{bersaglio}\footnote{si chiamano così, dall'inglese \textit{target},
  gli argomenti che si passano a \texttt{make} e che normalmente indicano
  quali delle varie sezioni dei comandi di costruzione e installazione scritti
  in un \texttt{Makefile} devono essere usati, non specificare nulla significa
  usare il primo \textit{target} disponibile che di norma esegue il compito
  principale; di solito ne esistono degli altri, ad esempio è comune
  \texttt{clean} che serve a cancellare i risultati della compilazione per
  riportare la directory del pacchetto nelle condizioni iniziali precedenti
  alla costruzione dello stesso, per ulteriori dettagli sul funzionamento di
  \texttt{make} si consulti \cite{Make}.} per \texttt{make} che consente la
disinstallazione con \texttt{make uninstall}. Ma se questo non c'è occorre
tracciarsi a mano i file che sono stati installati e cancellarli. In caso di
aggiornamento poi la cosa si complica ancora di più perché installando una
nuova versione potrà essere necessario sovrascrivere file, o installarne di
nuovi e cancellarne di vecchi, tutte cose che non sono quasi mai previste
dalla procedura di installazione di un pacchetto.

%TODO trattare checkinstall on futuro

Per questi motivi, come vedremo nelle sezioni seguenti, la gran parte delle
distribuzioni fornisce un sistema di gestione dei pacchetti che permetta di
tenere traccia di cosa si installa e di dove sono messi i file, che poi
consente sia una cancellazione pulita del pacchetto quando lo si vuole
disinstallare, che un aggiornamento corretto di tutto quello che serve
nell'uso di nuove versioni.


\subsection{La gestione dei pacchetti con \texttt{rpm} e \texttt{yum}}
\label{sec:adv_pkg_rmp}

Uno dei primi sistemi evoluti per la gestione dell'installazione e rimozione
di pacchetti software è RPM, realizzato da RedHat per la sua distribuzione. La
sigla originariamente stava per \textit{RedHat Package Manager}, essendo
utilizzato da molte altre distribuzioni oggi viene chiamato semplicemente
\textit{RPM Package Manager}. Data la sua efficacia esso è stato in seguito
adottato da molte altre distribuzioni, diventando uno dei sistemi di gestione
dei pacchetti più diffusi.

Con RPM si intende sia il programma \index{comando!\texttt{rpm}} \texttt{rpm},
che permette di eseguire l'installazione e la rimozione dei pacchetti, che il
formato dei file con cui sono distribuiti i pacchetti, normalmente
caratterizzati dalla estensione \texttt{.rpm}. In sostanza si tratta di
archivi \texttt{cpio} dei file necessari, tanto che esiste il comando
\index{comando!\texttt{rpm2cpio}} \texttt{rpm2cpio} che consente di estrarre
l'archivio \texttt{cpio} da un file \texttt{.rpm}.

In realtà il comando \texttt{rpm} fa molto di più che installare e
disinstallare: mantiene la lista dei pacchetti installati e di dove sono stati
installati i singoli file che ne fanno parte; così può accorgersi se un
pacchetto va in conflitto con altri cercando di installare gli stessi file.
Inoltre è in grado di accorgersi di dipendenze fra i vari pacchetti, di
effettuare verifiche su quanto è stato installato e di eseguire degli script
in fase di installazione e disinstallazione con cui eseguire procedure di
configurazione automatica del pacchetto stesso.

Il comando è complesso e prevede diverse modalità operative, attivate da
altrettante opzioni che non possono essere usate contemporaneamente. Le due
modalità più usate sono quella di installazione, attivata dall'opzione
\texttt{-i} e quella di rimozione, attivata dall'opzione \texttt{-e}. Altre
modalità usate spesso sono quella di interrogazione del database dei
pacchetti, attivata dall'opzione \texttt{-q} e quella di verifica attivata
dall'opzione \texttt{-V}. Per l'elenco completo si consulti la pagina di
manuale.

Nel caso si debbano installare dei pacchetti RPM occorre anzitutto procurarsi
i file \texttt{.rpm} con il relativo contenuto, l'opzione \texttt{-i} (o
\texttt{-{}-install}) di \texttt{rpm} infatti prende come argomento il file o
la lista di file dei nuovi pacchetti che si vogliono installare;
alternativamente si può usare negli argomenti una URL al posto del nome di un
file, nel qual caso il pacchetto indicato verrà anche scaricato direttamente
dalla rete via HTTP o FTP.

I pacchetti RPM seguono anche una convenzione precisa per i nomi dei file;
questi sono composti da più parti separate dal carattere ``\texttt{-}''. La
prima parte indica il nome del pacchetto stesso, e può essere anche composta
di più parole; segue il numero di versione, così come preso dalla versione
originale dal software, cui segue il cosiddetto numero di \textsl{revisione}
che marca le diverse versioni del pacchetto stesso. Infine segue, separate da
un punto, l'architettura per cui il pacchetto è stato realizzato e
l'estensione; in sostanza si avrà un nome del tipo:
\begin{Example}
logrotate-3.7.4-8.i386.rpm
\end{Example}

Nell'installare un pacchetto \texttt{rpm} controlla preliminarmente che tutte
le sue \textsl{dipendenze} siano soddisfatte, non installandolo in caso
contrario ed indicando dove sta il problema. Il comando si rifiuta di
installare il pacchetto anche se un file in esso contenuto esiste di già o se
un altro pacchetto con lo stesso nome è già installato. Questo significa che
non si può usare l'opzione \texttt{-i} per eseguire un aggiornamento, essa
deve essere usata soltanto per installare pacchetti \textsl{nuovi}.  Per
eseguire un aggiornamento sono previste due opzioni alternative: \texttt{-U}
(o \texttt{-{}-upgrade}) con cui si richiede l'installazione di nuovi
pacchetti e l'aggiornamento di eventuali pacchetti già installati, e
\texttt{-F} (o \texttt{-{}-freshen}) con cui si richiede il solo aggiornamento
di pacchetti già installati.

Si tenga presente che oltre a gestire le dipendenze, \texttt{rpm} è in grado
di gestire anche gli eventuali \textsl{conflitti}, cioè i casi in cui due
pacchetti (o due versioni diverse dello stesso pacchetto) cercano di
installare lo stesso file, ed in tal caso ovviamente dovrà essere generato un
errore. Esistono casi però in cui, ad esempio a causa di un aggiornamento ad
una versione di un pacchetto malfunzionante, può essere necessario evitare
questi controlli.

A tale scopo sono state fornite alcune opzioni di controllo da aggiungere a
\texttt{-i} per forzare l'installazione, come \texttt{-{}-replacefiles}, che
consente di installare il pacchetto anche se i file già sono presenti,
rimpiazzandoli, \texttt{-{}-replacepkgs} che consente di installare i
pacchetti anche se alcuni di essi sono già presenti e \texttt{-{}-oldpackage}
che consente di effettuare un aggiornamento sostituendo una versione più
recente dello stesso pacchetto con una precedente. É poi disponibile l'opzione
\texttt{-{}-force} che è una abbreviazione per l'uso di tutte e tre le opzioni
precedenti.

Come accennato la disinstallazione di un pacchetto viene eseguita con
l'opzione \texttt{-e} (o \texttt{-{}-erase}) cui segue il nome del pacchetto
o della lista dei pacchetti da rimuovere. Anche in questo caso vengono fatti
dei controlli preliminari, e ad esempio l'azione viene abortita se un altro
pacchetto dipende da quello che si vuole eliminare. Di nuovo può essere
necessario forzare la disinstallazione, cosa che può essere fatta specificando
la ulteriore opzione \texttt{-{}-nodeps}, che consente di ignorare i problemi
dovuti alle dipendenze (la stessa opzione è accettata anche da \texttt{-i}).

Con l'opzione \texttt{-q} (o \texttt{-{}-query}) è possibile eseguire una
serie di interrogazioni sul database dei pacchetti installati; se non si
specifica altro l'opzione richiede come argomento un nome di pacchetto di cui
verifica la presenza nel sistema. Ad essa però sono associate una lunga serie
di altre opzioni che consentono di ottenere informazioni più specifiche;
queste sono a loro volta suddivise in quelle che indicano quali informazioni
mostrare ed in quelle che indicano a chi applicare la richiesta.

Ad esempio con \texttt{rpm -qa} si ottiene la lista di tutti i pacchetti
installati nel sistema. Se invece si usa \texttt{-ql}, seguito dal nome del
pacchetto, si stampano i file in esso contenuti. Si può anche leggere il
contenuto di un pacchetto non installato con \texttt{-qpl} dove \texttt{-p}
serve a richiedere che come argomento si specifichi il file del
pacchetto. Qualora invece si volesse sapere a quale pacchetto appartiene un
file si potrà usare \texttt{-qf} indicando come argomento il file stesso.

La modalità di verifica viene attivata con l'opzione \texttt{-V} (o
\texttt{-{}-verify}) e richiede che si specifichi come argomento il nome di un
pacchetto installato o \texttt{-a} per eseguire la verifica su tutti
quanti. L'opzione consente di controllare l'integrità dei file che sono stati
installati da un pacchetto rispetto alle informazioni sullo stesso mantenute
nel database controllando se permessi, dimensioni e contenuto del file sono
coincidenti con quelli previsti. L'opzione provvede l'uso di ulteriori opzioni
per selezionare quali verifiche effettuare e restituisce per ciascun file una
stringa con i risultati delle verifiche.

Una altra opzione che consente di verificare il contenuto dei pacchetti è
\texttt{-{}-checksig}, che serve a controllare originalità e integrità di un
file contenente un pacchetto RPM, verificandone la firma digitale. Infine sono
degne di nota le opzioni \texttt{-{}-setperms} e \texttt{-{}-setugids} che
consentono di ripristinare ai valori originari permessi e proprietario di
tutti i file di un pacchetto, qualora li si siano modificati per errore.

In tab.~\ref{tab:adv_pkg_rpm_options} si sono riportate le principali opzioni
di \texttt{rpm}. La tabella è stata suddivisa in varie sezioni, accorpando
insieme le opzioni relative alla varie modalità di operazione del comando, e
lasciando nell'ultima parte le opzioni generiche. Per ciascuna sezione si sono
anche evidenziate, riportandole per prime, le opzioni obbligatorie che fanno
riferimento a quella modalità di operazioni e che devono essere presenti per
poter utilizzare le altre.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|l|l|}
    \hline
    \multicolumn{2}{|c|}{\textbf{Opzione}}&\textbf{Significato}\\
    \hline
    \hline
    \texttt{\textsl{-i}} & 
    \texttt{\textsl{-{}-install}}&installa un nuovo pacchetto.\\
    \texttt{\textsl{-U}} & 
    \texttt{\textsl{-{}-upgrade}}&aggiorna o installa un pacchetto.\\
    \texttt{\textsl{-F}} & 
    \texttt{\textsl{-{}-freshen}}&aggiorna un pacchetto già installato.\\
    & 
    \texttt{-{}-replacefiles}   & sovrascrive file di altri pacchetti.\\
    & 
    \texttt{-{}-replacepkgs}    & installa anche se il pacchetto è già
                                  installato.\\
    & 
    \texttt{-{}-oldpackage}     & installa una versione precedente a quella
                                  attuale.\\
    & 
    \texttt{-{}-force}          & riassume \texttt{-{}-replacefiles}, 
                                  \texttt{-{}-replacepkgs} e
                                  \texttt{-{}-oldpackage}.\\
    \texttt{-h}& 
    \texttt{-{}-hash}           & stampa una barra di progressione.\\ 
    \hline
    \texttt{\textsl{-e}} & 
    \texttt{\textsl{-{}-erase}} & rimuove un pacchetto.\\ 
    & 
    \texttt{-{}-nodeps}         & non verifica le dipendenze.\\ 
    \hline
    \texttt{\textsl{-q}} &
    \texttt{\textsl{-{}-query}} & interroga il database per la presenza di un
                                  pacchetto.\\   
    \texttt{-a}&
    \texttt{-{}-all}            & stampa tutti i pacchetti installati.\\ 
    \texttt{-l}&
    \texttt{-{}-list}           & stampa i file contenuti in un pacchetto.\\ 
    \texttt{-f}&
    \texttt{-{}-file}           & stampa il pacchetto che contiene un file.\\ 
    \texttt{-p}&
    \texttt{-{}-package}        & stampa il contenuto del pacchetto contenuto
                                  nel file.\\  
    & 
    \texttt{-{}-whatrequires}   & indica quali pacchetti dipendono da una
                                  certa funzionalità.\\
    & 
    \texttt{-{}-whatprovides}   & indica quali pacchetti forniscono una certa 
                                  funzionalità.\\
    \hline
    \texttt{-V}&
    \texttt{-{}-verify}          & verifica lo stato di un pacchetto.\\ 
    \texttt{-K}&
    \texttt{-{}-checksig}        & verifica la firma digitale di un
                                   pacchetto.\\  
    \texttt{-v} &                & stampa più informazioni nell'esecuzione
                                   delle operazioni.\\  
    & 
    \texttt{-{}-setperms}        & ripristina i permessi dei file del
                                   pacchetto.\\ 
    &
    \texttt{-{}-setugids}        & ripristina proprietario e gruppo dei file
                                   del pacchetto.\\ 
    \hline
  \end{tabular}
  \caption{Principali opzioni del comando \texttt{rpm} suddivise per
    categorie.} 
  \label{tab:adv_pkg_rpm_options}
\end{table}

A lungo \texttt{rpm} è stato in grado di gestire le dipendenze solo in forma
molto elementare, avvisando l'utente di quali erano i file che dovevano essere
già presenti nel sistema perché un certo pacchetto potesse essere installato,
con il non banale svantaggio di costringere l'amministratore ad indovinare
quale potesse essere il pacchetto che li conteneva. Nelle versioni più recenti
sono state però aggiunte funzionalità più evolute in grado di eseguire il
controllo delle dipendenze a livello di pacchetto e non di singolo file, e
sono state introdotte anche nuove opzioni di interrogazione da abbinare
all'opzione \texttt{-q}, come \texttt{-{}-whatprovides}, che indica quali
pacchetti forniscono una certa funzionalità, e \texttt{-{}-whatrequires} che
indica tutti i pacchetti che ne richiedono un altro per funzionare.

In questo modo il programma permette di sapere quali sono i pacchetti che non
funzioneranno a causa della mancanza di un qualche componente a loro
essenziale che potrà essere fornito da altri pacchetti.  Il meccanismo fornito
da \texttt{rpm} però si limita a questo, sta all'amministratore trovare,
scaricare ed installare i pacchetti mancanti, il che porta a quella situazione
che viene chiamata \textit{dependency hell}, quando un pacchetto dipende da un
altro che a sua volta dipende da una altro che a sua volta... Tutto questo a
meno che la propria distribuzione non fornisca un sistema di gestione dei
pacchetti di più alto livello, come \texttt{yum} o la versione per RPM del
sistema APT di Debian, che tratteremo nella prossima sezione.

A lungo infatti le distribuzioni basate su RPM sono state prive di un sistema
di gestione dei pacchetti di alto livello presente invece su Debian e sulle
sue derivate, che permettesse di gestire in maniera più semplice le dipendenze
e gli aggiornamenti del software. Per questo ognuna ha finito per sviluppare
un suo sistema diverso. Fra questi quello che ha avuto il maggior successo, e
che si avvicina di più alle funzionalità presenti su Debian è
\index{comando!\texttt{yum}} \texttt{yum}, il cui nome sta per
\textit{Yellowdog Updater Modified} essendo stato creato inizialmente da
Yellowdog, ed in seguito modificato ed adottato da altre distribuzioni, come
RedHat.

Il concetto generale di \texttt{yum}, ripreso pari pari dall'APT di Debian, è
quello di avere una o più fonti, i cosiddetti \textit{repository}, su cui sono
contenuti sia i pacchetti che le informazioni ad essi relative (come le
dipendenze reciproche, le versioni, ecc.), organizzate in maniera
opportuna. Facendo riferimento ad un \textit{repository} si potrà allora
conoscere quali pacchetti sono disponibili, quali sono necessari per poterne
installare un altro o di quali pacchetti esiste una versione più recente, da
usare come aggiornamento.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Operazione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{install}     & installa un pacchetto.\\ 
    \texttt{check-update}& verifica se sono disponibili aggiornamenti.\\ 
    \texttt{update}      & esegue l'aggiornamento dei pacchetti installati.\\ 
    \texttt{upgrade}     & esegue l'aggiornamento anche da una distribuzione
                           precedente.\\  
    \texttt{remove}      & rimuove un pacchetto.\\ 
    \texttt{erase}       & sinonimo di \texttt{remove}.\\ 
    \texttt{list}        & stampa un elenco dei pacchetti.\\ 
    \texttt{info}        & stampa informazioni descrittive sui pacchetti.\\ 
    \texttt{clean}       & cancella la cache dei pacchetti scaricati.\\ 
    \texttt{search}      & esegue una ricerca della stringa passata come
                           argomento nelle descrizioni e nei nomi dei
                           pacchetti.\\
    \hline
  \end{tabular}
  \caption{Principali operazioni di \texttt{yum}.} 
  \label{tab:yum_commands}
\end{table}

In genere \texttt{yum} viene invocato passandogli come primo argomento
l'operazione che si vuole eseguire, seguita da eventuali altri argomenti
successivi. Se ad esempio si vuole installare un pacchetto sarà necessario
usare l'operazione \texttt{install} e specificare poi il nome dello stesso. In
questo caso basta il nome del pacchetto, usando dei \textit{repository} non è
necessario né il nome di un file né un numero di versione. Specificando più
nomi verrà richiesta l'installazione di più pacchetti. Sarà cura poi di
\texttt{yum} scaricare ed installare preventivamente a quelli richiesti anche
gli ulteriori pacchetti aggiuntivi ritenuti necessari a soddisfare le
dipendenze.

Viceversa per rimuovere un pacchetto (o più) si può utilizzare l'operazione
\texttt{erase} (o l'omonima \texttt{remove}) seguita dal nome (o dai nomi) dei
pacchetti da rimuovere, mentre l'aggiornamento viene effettuato con
\texttt{update}, anche in questo caso si può passare una lista di nomi, nel
qual caso saranno aggiornati solo i pacchetti indicati. A questa si aggiunge
\texttt{upgrade} che tiene in considerazione anche gli aggiornamenti dai
pacchetti installati da una distribuzione precedente l'attuale.

Infine con \texttt{list} si possono elencare tutti i pacchetti disponibili
(con versione e \textit{repository} su cui si trovano) mentre con
\texttt{info} se ne possono ottenere le relative informazioni, entrambe le
operazioni riconoscono come parametri aggiuntivi, oltre ad un elenco di nomi
di pacchetti, per i quali è anche possibile usare le \textit{wildcard} del
\textit{filename globbing}, le parole chiave \texttt{all} che elenca tutti i
pacchetti, \texttt{available} che elenca quelli disponibili per
l'installazione, \texttt{updates} che elenca gli aggiornamenti,
\texttt{installed} che elenca quelli installati ed \texttt{extras} che elenca
quelli installati ma non presenti in nessun \textit{repository}.

Se invece di installare un pacchetto lo si volesse soltanto scaricare,
\texttt{yum} non supporta direttamente l'operazione, ed occorre fare ricorso
ad un comando ausiliario, \index{comando!\texttt{yumdownloader}}
\texttt{yumdownloader}, che prende come argomenti una lista di pacchetti e li
scarica nella directory corrente. Il comando consente di specificare una
directory diversa con \texttt{-{}-destdir} e di richiedere, se disponibile, il
corrispondente pacchetto sorgente con l'opzione \texttt{-{}-source}.

Per il funzionamento di \texttt{yum} e dei relativi comandi ausiliari occorre
però poter fare riferimento agli opportuni \textit{repository} che contengono
i pacchetti ed il comando potrà accedere al contenuto degli stessi per
ottenere automaticamente tutto quello che serve. L'accesso ad un
\textit{repository} può essere eseguito in una molteplicità di modi, ma i
principali sono via rete con i protocolli HTTP o FTP, o direttamente tramite
il contenuto, opportunamente strutturato, di una directory del proprio
disco. 

Il file di configurazione principale di \texttt{yum} è
\index{configurazione!\texttt{/etc/yum.conf}} \texttt{/etc/yum.conf}, ma il
programma riconosce anche \texttt{/etc/yum/yum.conf}.  Questo file usa il
formato dei \textit{keyfile} illustrato in sez.~\ref{sec:cfg_general}, che
prevede delle sezioni introdotte da un nome posto fra parentesi quadre,
all'interno delle quali si possono impostare le varie opzioni di
configurazione nella forma di assegnazione di un valore ad una parola
chiave. Un esempio di questo file, preso dalla versione installata su una
Scientific Linux 6.2, è il seguente:
\begin{FileExample}[label=/etc/yum.conf]
[main]
cachedir=/var/cache/yum/$basearch/$releasever
keepcache=0
debuglevel=2
logfile=/var/log/yum.log
exactarch=1
obsoletes=1
gpgcheck=1
plugins=1
installonly_limit=3
...
\end{FileExample}

Il file richiede sempre la presenza di una (ed una sola) sezione
\texttt{main}, che contiene le configurazioni generali del comando; è qui ad
esempio che si può impostare, qualora sia necessario, l'utilizzo di un proxy
web per il download dei pacchetti, assegnando all'opzione \texttt{proxy} la
URL dello stesso (utilizzando poi le ulteriori \texttt{proxy\_username} e
\texttt{proxy\_password} per indicare eventuali credenziali di accesso). 

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{cachedir} & imposta la directory dove sono mantenuti i pacchetti 
                        scaricati e le relative informazioni.\\ 
    \texttt{logfile}  & imposta il file con il registro delle operazioni 
                        effettuate da \texttt{yum} (installazioni,
                        aggiornamenti, rimozioni, ecc.).\\ 
    \texttt{gpgcheck} & richiede o meno il controllo della firma con GPG dei
                        pacchetti (rispettivamente con i valori ``1'' o
                        ``0'').\\
    \texttt{pkgpolicy}& imposta la politica da seguire quando lo stesso
                        pacchetto è disponibile su diversi repository, con
                        \texttt{newest} installa sempre la versione più
                        recente, con \texttt{last} installa la versione
                        presente nel \textit{repository} che viene per ultimo
                        nella lista degli stessi fatta per ordine alfabetico
                        sul relativo identificatore.\\ 
%    \texttt{plugins}  & abilita o meno l'uso dei \textit{plugin} di
%                        \texttt{yum} (rispettivamente con i valori ``1'' o
%                        ``0'').\\  
    \texttt{proxy}    & imposta l'uso di un \textit{proxy}, da specificare
                        tramite la relativa URL.\\ 
    \texttt{proxy\_password}& imposta una password per l'accesso al
                        \textit{proxy}.\\ 
    \texttt{proxy\_username}& imposta un utente per l'accesso al
                        \textit{proxy}.\\ 
    \texttt{reposdir} & imposta la directory (o le directory) da cui prendere
                        la lista dei file \texttt{.repo} che definiscono i
                        \textit{repository}, il default è
                        \texttt{/etc/yum.repos.d/}.\\
    \texttt{tolerant} & rende il comando più tollerante (rispettivamente con i
                        valori ``1'' o ``0'') rispetto ad alcune classi di
                        errori (come richiedere l'installazione di un
                        pacchetto già installato).\\  
    \hline
  \end{tabular}
  \caption{Principali opzioni della sezione \texttt{main} di
    \texttt{yum.conf}.}  
  \label{tab:yum_conf_options}
\end{table}

Altre opzioni comuni, presenti anche nel precedente esempio, sono
\texttt{cachedir} che imposta la directory dove verranno mantenuti i pacchetti
scaricati ed i dati ad essi associati, e \texttt{logfile} che indica il file
su cui vengono registrati i risultati delle varie operazioni. Oltre a queste
sono definite una grande quantità di altre opzioni che consentono di
controllare nei dettagli i vari aspetti di funzionamento del comando; le
principali sono riportate in tab.~\ref{tab:yum_conf_options} ma per i dettagli
al solito occorre fare riferimento alla pagina di manuale, accessibile con
\texttt{man yum.conf}.

Benché sia possibile indicare direttamente all'interno di \texttt{yum.conf} i
\textit{repository} che si vogliono utilizzare, definendo per ciascuno di essi
altrettante sezioni, normalmente viene definita solo la sezione \texttt{main}
e si preferisce usare a tale scopo una serie di file separati, caratterizzati
dall'estensione \texttt{.repo}, che di default sono mantenuti nella directory
\index{configurazione!\texttt{/etc/yum.repos.d/}} \texttt{/etc/yum.repos.d/}
(ma se può indicare un'altra con il valore della direttiva \texttt{reposdir}
di \texttt{yum.conf}). In questo modo per aggiungere un nuovo
\textit{repository} è sufficiente installare un altro file all'interno di
essa.

Il formato di un file \texttt{.repo} prevede che esso sia nella forma di una o
più sezioni associate ad altrettanti \textit{repository}. Il nome di ciascuna
sezione, nella forma di una singola parola, deve essere sempre diverso in
quanto viene a costituire il cosiddetto \textit{repository id} che serve come
riferimento univoco per identificare uno specifico \textit{repository}. Ad
esempio nel caso di CentOS 5.2 viene usato un file \texttt{CentOS-Base.repo}
che definisce le sezioni \texttt{base}, \texttt{updates}, \texttt{addons},
\texttt{extras} e \texttt{centosplus} per l'uso dei \textit{repository}
ufficiali supportati da questa distribuzione, corrispondenti rispettivamente
ai pacchetti di base, agli aggiornamenti, e ad una serie di diverse estensioni
e pacchetti aggiuntivi. In generale ogni distribuzione fornirà i suoi
\textit{repository} ufficiali.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{name}      & una stringa di descrizione del \textit{repository}.\\ 
    \texttt{baseurl}   & la URL che indica l'indirizzo a cui è possibile
                         raggiungere i contenuti del \textit{repository}.\\ 
    \texttt{mirrorlist}& si può usare al posto di \texttt{baseurl} per
                         indicare un file che contiene una lista di URL.\\ 
    \texttt{gpgkey}    & la URL da cui scaricare la chiave pubblica GPG per la
                         verifica di autenticità del pacchetto.\\ 
% TODO manca riferimento
    \texttt{exclude}   & una lista, separata da spazi, di pacchetti da non
                         prendere in considerazione anche se presenti,
                         supporta anche l'uso dei caratteri jolly del
                         \textit{filename globbing}.\\
    \texttt{enabled}   & consente di disabilitare il \textit{repository} 
                         se posto a 0, il valore di default è 1.\\ 
    \hline
  \end{tabular}
  \caption{Principali opzioni usabili per le sezioni che identificano un
    \textit{repository}.}   
  \label{tab:yum_conf_repo}
\end{table}

Ciascuna sezione dovrà poi contenere le opzioni che consentono di utilizzare
il \textit{repository} da essa identificato, la principale di queste è
\texttt{baseurl}, che prende come argomento la URL a cui è possibile
raggiungere i contenuti del repository. Le forme supportate sono
\texttt{http://} per l'accesso HTTP, \texttt{ftp://} per l'accesso FTP e
\texttt{file://} per l'accesso su una directory locale. Oltre a questa si sono
riportate le altre opzioni principali in tab.~\ref{tab:yum_conf_repo}; come al
solito per i dettagli si consulti la pagina di manuale.

% TODO trattare gli script di ausilio


\subsection{Il sistema di gestione dei pacchetti APT}
\label{sec:adv_pkg_debian}

Uno dei punti di forza di Debian è il sistema di gestione dei pacchetti creato
da questa distribuzione; il sistema si chiama APT, sigla che sta per
\textit{Advanced Package Tool}.  Anche in questo caso c'è un programma di base
per la gestione dei singoli pacchetti, con funzionalità analoghe a quelle di
\texttt{rpm}, questo però è solo una parte di una infrastruttura molto più
ampia, che consente una gestione semplice e funzionale dell'installazione di
pacchetti software.

I pacchetti Debian sono distribuiti in file con l'estensione \texttt{.deb} ed
anch'essi seguono una precisa convenzione relativa ai nomi che in questo caso
sono composti da più parti tutte separate dal carattere ``\texttt{\_}''.  La
prima parte indica il nome del pacchetto stesso, e può essere anche composta
di più parole. Segue la versione del pacchetto che è composta da due parti
separate da un ``\texttt{-}'': il numero di versione del software originale,
ed il numero di \textsl{revisione} che marca le diverse versioni del pacchetto
stesso. Infine segue l'architettura per cui il pacchetto è stato realizzato e
l'estensione, in sostanza si avrà un nome del tipo:
\begin{Example}
logrotate_3.7.1-3_i386.deb
\end{Example}

Il programma di base analogo a \texttt{rpm} è \index{comando!\texttt{dpkg}}
\texttt{dpkg}, anche se in realtà \texttt{dpkg} è nato prima di \texttt{rpm},
per cui forse sarebbe più corretto dire che \texttt{rpm} è analogo a
\texttt{dpkg}. Il comando fornisce le stesse funzionalità: installa e rimuove
pacchetti mantenendo un database dei pacchetti e dei relativi file installati,
provvede all'esecuzione di script in fase di installazione e rimozione, è in
grado di accorgersi di eventuali conflitti con pacchetti già installati, e
delle dipendenze da altri pacchetti, può interrogare il database dei pacchetti
e ottenere informazioni sul loro contenuto.

Le opzioni principali del comando sono \texttt{-i}, che esegue l'installazione
di un file \texttt{.deb}, e \texttt{-r}, che rimuove un pacchetto dal
sistema. Con \texttt{-l} se non si specifica nulla viene stampata la lista dei
pacchetti installati, mentre se si specifica un nome viene ricercata la
presenza di un pacchetto con quel nome. Con \texttt{-L} si può stampare la
lista dei file contenuti nel pacchetto e con \texttt{-S} quella dei pacchetti
che contengono un file corrispondente alla stringa passata come parametro. Le
altre opzioni principali sono riportate in tab.~\ref{tab:dpkg_options}. Al
solito le istruzioni complete e tutte le altre opzioni sono descritte nella
pagina di manuale.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-i} & installa il pacchetto.\\ 
    \texttt{-r} & rimuove il pacchetto.\\ 
    \texttt{-l} & interroga il database per la presenza di un pacchetto.\\ 
    \texttt{-L} & stampa i file contenuti in un pacchetto.\\ 
    \texttt{-S} & ricerca i pacchetti che contengono un file.\\ 
    \texttt{-s} & stampa lo \textit{stato} di un pacchetto.\\ 
    \texttt{-p} & stampa informazioni su un pacchetto installato.\\ 
    \texttt{-I} & stampa informazioni su un \texttt{.deb}.\\ 
    \texttt{-c} & stampa il contenuto di un \texttt{.deb}.\\ 
    \hline
  \end{tabular}
  \caption{Principali opzioni del comando \texttt{dpkg}.}
  \label{tab:dpkg_options}
\end{table}

Benché ormai anche i \texttt{.deb} risultino piuttosto usati, dato che sono
diventate parecchie le distribuzioni basate su Debian, la loro diffusione su
Internet come file singoli è piuttosto ridotta. Questo avviene proprio perché
praticamente da sempre \texttt{dpkg} costituisce soltanto la parte di basso
livello del sistema di gestione dei pacchetti di Debian, per cui è piuttosto
raro dover usare questo comando per installare un pacchetto.

Come accennato infatti uno dei grandi vantaggi di questa distribuzione, e di
quelle che usano lo stesso sistema di gestione, è costituito dalla interfaccia
di alto livello costituita da APT, che permette di dimenticarsi completamente
del problema delle dipendenze. I pacchetti Debian infatti sono stati
organizzati fin dall'inizio per indicare in maniera coerente da quali altri
pacchetti essi dipendono. Diventa così possibile richiedere l'installazione
automatica non solo di un singolo pacchetto, ma anche di tutti quelli da cui
questo dipende. Inoltre in genere i pacchetti vengono distribuiti direttamente
via rete, con una modalità che permette il download automatizzato degli
stessi.

Il programma di gestione principale per i pacchetti Debian non è allora
\texttt{dpkg}, ma \texttt{apt-get}, che serve appunto da front-end per tutto
il sistema dell'\textit{Advanced Package Tool}. Ad esso si è aggiunto il
comando \texttt{aptitude}, che oltre a funzionare a riga di comando fornisce
anche una interfaccia testuale semi-grafica. Dato che \texttt{apt-get}
fornisce in sostanza un sottoinsieme delle funzionalità di \texttt{aptitude},
parleremo prima di lui.

Per il corretto funzionamento del sistema di APT è fondamentale mantenere una
lista delle necessarie fonti dei pacchetti (i \textit{repository}) nel file
\index{configurazione!\texttt{/etc/apt/sources.list}}
\texttt{/etc/apt/sources.list}. Le versioni più recenti di APT prevedono anche
l'uso della directory \index{configurazione!\texttt{/etc/apt/sources.list.d/}}
\texttt{/etc/apt/sources.list.d/} dove si possono indicare fonti aggiuntive;
in tal caso è sufficiente inserire in questa directory un file con
l'estensione \texttt{.list} e lo stesso formato di \texttt{sources.list}, ed
il suo contenuto sarà utilizzato come se lo si fosse incluso in
quest'ultimo. 

Il formato del file \texttt{sources.list} prevede una serie di righe formate
da campi divisi da spazi, ciascuna delle quali indica una fonte di
pacchetti. Il primo campo indica il tipo di pacchetti presenti in quel
\textit{repository}; originariamente i soli valori possibili erano
\texttt{deb} e \texttt{deb-src}, per indicare rispettivamente pacchetti binari
e sorgenti. Il sistema di APT però è stato portato anche su distribuzioni
basate su RPM, sulle quali è possibile utilizzare per questo campo il valore
\texttt{rpm}.

Il secondo campo è una URI per l'accesso al \textit{repository} che indica la
base del rispettivo archivio. Come accennato l'accesso può essere effettuato
in modalità diverse, le principali delle quali sono indicate con le URI
riportate in tab.~\ref{tab:sources_list_uri}, a cui dovrà seguire la opportuna
specificazione della posizione del \textit{repository}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{URI} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{file:}  & accede ai pacchetti posti in una directory locale (o
                      anche remota se si usa NFS, vedi
                      sez.~\ref{sec:net_NFS_client}).\\  
    \texttt{cdrom:} & accede ai pacchetti su un CDROM, una voce di questo tipo
                      deve essere creata con l'ausilio di \texttt{apt-cdrom}.\\ 
    \texttt{http:}  & un ordinario riferimento ad un sito web.\\ 
    \texttt{ftp:}   & un ordinario riferimento ad un sito FTP.\\ 
    \hline
  \end{tabular}
  \caption{Principali formati delle URI usate in \texttt{sources.list}.} 
  \label{tab:sources_list_uri}
\end{table}

I campi successivi prevedono due diverse sintassi. La prima è quella in cui si
specifica in un unico campo il pathname della directory in cui si trovano i
pacchetti, così come viene vista relativamente alla base specificata con la
URI del secondo campo. In questo caso il campo deve essere obbligatoriamente
terminato dal carattere ``\texttt{/}'' per distinguerlo dall'altra
sintassi. Si usa in genere questa forma per dei \textit{repository} elementari
in cui tutti i pacchetti sono stati inseriti in una unica directory.

Nella seconda sintassi il terzo campo indica invece il nome associato alla
versione della distribuzione che si sta usando. Per Debian è sempre possibile
usare i nomi generici \texttt{stable}, \texttt{testing} ed \texttt{unstable}
ad indicare rispettivamente la versione stabile, quella di test e quella di
sviluppo; a ciascuno di questi viene anche associato un nome proprio, che per
\texttt{unstable} è sempre \texttt{sid}, mentre per le altre varia da rilascio
a rilascio.\footnote{i nomi vengono presi dai personaggi del film
  ``\textit{Toy Story}'', al momento della scrittura di questa sezione la
  versione stabile è \texttt{squeeze} mentre quella di test è
  \texttt{wheezy}.}  A questo segue almeno un campo aggiuntivo che indica la
\textsl{sezione} del \textit{repository} a cui si vuole avere accesso; nel
caso di Debian le sezioni sono tre e cioè \texttt{main}, \texttt{contrib} e
\texttt{non-free}.  Sia il nome della versione, che le sezioni in cui essa è
divisa, dipendono dalla distribuzione; ad esempio con Ubuntu, al momento della
stesura di queste note, la versione corrente è \texttt{lucid}, mentre le
sezioni utilizzate sono \texttt{main}, \texttt{restricted}, \texttt{universe}
e \texttt{multiverse}.

Quando si usa questa seconda sintassi, che è quella usata di default per i
repository ufficiali dalle distribuzioni che usano APT, si fa riferimento a
dei \textit{repository} più strutturati, in cui i pacchetti sono
opportunamente organizzati in opportune directory.\footnote{i dettagli di
  tutto ciò vanno oltre lo scopo di questo testo, gli interessati possono
  consultare il capitolo 4 di \cite{DebSys}.} Si noti anche come in nessuno
dei due casi si sia fatto riferimento alla architettura hardware per la quale
sono compilati i pacchetti binari; con la prima sintassi questo avviene perché
i \textit{repository} specificati in quella forma non supportano l'uso di
architetture multiple, per cui si deve avere cura di indicarne con pacchetti
adatti alla propria. Nel secondo caso invece non è necessario perché la scelta
dei pacchetti corretti viene fatta in maniera automatica.

In genere la configurazione di un \textit{repository} si fa semplicemente
aggiungendo le righe necessarie a \texttt{sources.list}, l'unico caso che
necessita di una cura particolare è quello relativo ai pacchetti di un CDROM,
in cui la riga di configurazione deve essere creata con il programma
\index{comando!\texttt{apt-cdrom}} \texttt{apt-cdrom}, che si incarica di
verificare il contenuto di un CD e generare una voce con le informazioni
necessarie, che permette di evitare problemi qualora si cambiasse disco nel
lettore.

In genere se si è installato il sistema da uno o più CD o DVD la relativa voce
completa viene creata automaticamente in fase di installazione ed è necessario
modificarla solo se si vogliono usare altri supporti. Per l'uso del comando si
può consultare la pagina di manuale, ma in generale tutto quello che c'è da
fare è inserire il CD nel lettore ed eseguire \texttt{apt-cdrom add}. In
seguito quando verrà richiesta l'installazione di un pacchetto dal CD sarà lo
stesso \texttt{apt-get} a richiederne l'inserimento nel lettore.

Si tenga presente che è possibile indicare anche diversi \textit{repository},
sia per indicare fonti aggiuntive di pacchetti. Ad esempio nel caso di Debian
oltre al \textit{repository} dei pacchetti ordinari si usa indicare anche
quello degli aggiornamenti, su cui vengono inseriti tutti i pacchetti
rilasciati per chiudere bug di sicurezza, che è mantenuto centralmente dal
\textit{security team} del progetto. Si possono anche indicare più righe con i
mirror degli stessi \textit{repository} per poter scaricare da diverse fonti
gli stessi pacchetti in caso una non fosse raggiungibile. In quest'ultimo caso
si tenga conto che la scansione avviene in ordine sequenziale, per cui è
opportuno mettere prima quelle più vicine. Un esempio del file
\texttt{sources.list}, tratto dalla versione presente (con l'installazione via
rete) su una Debian Squeeze, è il seguente:
\begin{FileExample}[label=/etc/apt/sources.list]
# deb cdrom:[Debian GNU/Linux 6.0.0 _Squeeze_ - Official i386 NETINST Binary-1
 20110205-14:34]/ squeeze main

deb http://ftp.it.debian.org/debian/ squeeze main
deb-src http://ftp.it.debian.org/debian/ squeeze main

deb http://security.debian.org/ squeeze/updates main
deb-src http://security.debian.org/ squeeze/updates main

deb http://ftp.it.debian.org/debian/ squeeze-updates main
deb-src http://ftp.it.debian.org/debian/ squeeze-updates main
\end{FileExample}
dove, sia per i pacchetti binari che per i sorgenti, è stato indicato un
mirror italiano dei \textit{repository} ufficiali di Debian, ed il
\textit{repository} speciale relativo agli aggiornamenti di sicurezza.


Una volta impostati i vari \textit{repository} il comando che consente di
operare sui pacchetti è, come accennato, \index{comando!\texttt{apt-get}}
\texttt{apt-get}. Questo prende sempre come primo argomento una parola chiave
che indica l'operazione da eseguire, seguito da eventuali altri argomenti,
quando previsti. Si tenga presente che in generale, per evitare pericolosi
intrecci, è possibile eseguire una sola istanza alla volta di \texttt{apt-get}
o di qualunque altro programma che operi sulla installazione dei pacchetti. Se
pertanto è già in corso una operazione sui pacchetti \texttt{apt-get} si
bloccherà notificando che il sistema di gestione di APT è in già in uso.

In generale il primo passo da fare per operare con \texttt{apt-get} è eseguire
il comando \texttt{apt-get update} per scaricare una lista aggiornata di tutti
i pacchetti disponibili.  Sarà possibile poi installare un pacchetto qualunque
con il comando \texttt{apt-get install nomepacchetto}, dove il nome del
pacchetto corrisponde alla prima parte (quella che precede il primo
``\texttt{\_}'') del nome del file che lo contiene. Il programma si
incaricherà di effettuare automaticamente il download dello stesso e di quelli
necessari per soddisfare eventuali dipendenze, per poi procedere ad installare
il tutto. Qualora si voglia reinstallare un pacchetto già installato, si dovrà
aggiungere l'opzione \texttt{-{}-reinstall}.

Il comando gestisce anche eventuali \textsl{conflitti}, se ad esempio si cerca
di installare un pacchetto che fornisce in maniera alternativa lo stesso
servizio di un altro occorrerà prima rimuovere quest'ultimo. In questo caso,
ed anche tutte le volte che è necessario installare altri pacchetti a causa
delle dipendenze, il comando si ferma indicando quali pacchetti intende
installare e quali rimuovere, e chiede una conferma prima di procedere nelle
sue operazioni.

Si tenga presente poi che oltre alla installazione, nel sistema di gestione
dei pacchetti Debian è integrato anche un meccanismo per l'auto-configurazione
dei programmi (chiamato \textit{debconf}) che fornisce una interfaccia
generica con cui richiedere all'amministratore le informazioni necessarie per
generare automaticamente una configurazione corretta o notificargli eventuali
azioni necessarie per completare la configurazione.  Il meccanismo è
realizzato dall'omonimo pacchetto \texttt{debconf}, che può essere
opportunamente configurato per richiedere un quantitativo maggiore o minore di
dettagli, fino all'estremo di non fare chiedere nulla e generare un default
generico (probabilmente non funzionante); si tenga presente che il sistema è
opzionale e non è detto che sia utilizzato da tutti i pacchetti.

Questo risulta molto utile in caso di installazione di programmi di servizio,
dato che in questo modo APT non solo installa il pacchetto, ma lo configura e
rende immediatamente attivo. Pertanto la procedura di installazione può venire
sospesa in attesa di una risposta da parte dell'amministratore. Un'altra
caratteristica di \textit{debconf} è che può essere configurata la modalità
con cui viene eseguita la richiesta, il default è utilizzare una interfaccia
semi-grafica a terminale, ma esistono varie alternative.

Qualora si voglia rimuovere un pacchetto il comando è \texttt{apt-get remove
  nomepacchetto}, ed in questo caso, se altri pacchetti dipendono da quello
che si vuole rimuovere, il comando chiede conferma della volontà di rimuovere
anche loro, ed in caso affermativo procede alla rimozione anche di questi. Una
delle caratteristiche di Debian è che la rimozione di un pacchetto non
comporta normalmente la rimozione dei relativi file di configurazione, che
potrebbero tornare utili in una successiva reinstallazione. Se si vuole
rimuovere definitivamente anche tutte le configurazioni occorre aggiungere al
precedente comando l'opzione \texttt{-{}-purge}.

Infine il sistema di APT consente una estrema facilità di aggiornamento del
sistema, basta infatti usare il comando \texttt{apt-get upgrade} dopo aver
usato \texttt{apt-get update} per ottenere automaticamente l'aggiornamento a
eventuali nuove versioni presenti sui \textit{repository} di tutti i pacchetti
che sono già installati nel sistema. Il comando però non esegue mai un
aggiornamento se questo comporta l'installazione di pacchetti aggiuntivi o la
rimozione di un pacchetto già presente dal sistema, anche quando questo
verrebbe sostituito da una diversa versione più aggiornata.\footnote{in
  genere il problema si presenta per librerie o per programmi che vengono
  suddivisi in più parti, in tal caso se cambia il numero di versione della
  libreria cambia il nome del relativo pacchetto, mentre può non cambiare il
  nome del pacchetto che la usa, oppure un pacchetto può essere spezzato in
  più parti e quello originario non esiste più e devono essere installate
  tutte le varie parti.}

Per risolvere questo tipo di situazioni, che nell'uso di una versione stabile
si incontrano soltanto quando si effettua l'aggiornamento ad una versione
stabile successiva, si deve usare il comando \texttt{apt-get dist-upgrade} che
esegue una risoluzione intelligente dei conflitti ed è in grado di effettuare
l'aggiornamento dei pacchetti principali a scapito di quelli secondari,
accorgersi delle sostituzioni di pacchetti, installare le parti che mancano,
ecc. 

Qualora si usi una versione di test o di sviluppo, cioè \texttt{testing} o
\texttt{unstable}, la situazione descritta invece è comune e capita spesso di
dover usare \texttt{dist-upgrade}. In tal caso si ponga attenzione alle
eventuali rimozioni proposte, che vengono sempre indicate dal comando, il
quale prima di operare chiede conferma mostrando i pacchetti che installerà e
quelli che rimuoverà. In caso di errori nelle dipendenze dei pacchetti, che
nelle versioni di sviluppo si verificano con una certa frequenza, specie
quando viene fatta una transizione a nuove versioni, si potrebbe rischiare di
rimuovere parti essenziali per il funzionamento di altri pacchetti.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|l|}
    \hline
    \textbf{Operazione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{install}     & installa un pacchetto.\\ 
    \texttt{remove}      & rimuove un pacchetto.\\ 
    \texttt{update}      & scarica la lista aggiornata dei pacchetti.\\ 
    \texttt{upgrade}     & esegue l'aggiornamento dei pacchetti installati.\\ 
    \texttt{dist-upgrade}& esegue l'aggiornamento della distribuzione.\\ 
    \texttt{clean}       & cancella l'archivio dei pacchetti scaricati.\\ 
    \texttt{download}    & scarica il pacchetto nella directory corrente.\\ 
    \texttt{autoclean}   & cancella dall'archivio le 
                           vecchie versioni dei pacchetti scaricati.\\ 
    \hline
  \end{tabular}
  \caption{Principali operazioni dei comandi \texttt{apt-get} e
    \texttt{aptitude}.} 
  \label{tab:adv_pkg_aptget_options}
\end{table}

Altre operazioni di \texttt{apt-get} riguardano la gestione dell'archivio dei
pacchetti scaricati, che normalmente vengono mantenuti in una apposita
directory (\texttt{/var/cache/apt/archive}) così che non ci sia da
riscaricarli qualora si debbano reinstallare.  Le principali operazioni di
\texttt{apt-get} sono riportate in tab.~\ref{tab:adv_pkg_aptget_options},
l'elenco completo, insieme alla descrizione dettagliata di tutte le
caratteristiche del comando, è al solito disponibile nella relativa pagina di
manuale.

Il comando supporta inoltre alcune opzioni generiche, oltre le già citate
\texttt{-{}-reinstall} e \texttt{-{}-purge} che sono specifiche
dell'operazione \texttt{install}. In particolare con \texttt{-d} si può
richiedere che i pacchetti necessari per una operazione siano soltanto
scaricati, mentre con \texttt{-f} è possibile richiedere un tentativo di
correzione in caso di sistema in cui le dipendenze sono state spezzate, ad
esempio da un aggiornamento interrotto. Per i dettagli si consulti al riguardo
la pagina di manuale.

\begin{figure}[!htb]
\centering
\includegraphics[scale=0.5]{images/aptitude}
\caption{Schermata di avvio di \texttt{aptitude}.}
\label{fig:aptitude_screen}
\end{figure}

Le operazioni di tab.~\ref{tab:adv_pkg_aptget_options} sono utilizzate anche
dal comando \index{comando!\texttt{aptitude}} \texttt{aptitude}, una
implementazione alternativa che per un certo tempo è stato indicato come il
programma ufficialmente deputato alla gestione dei pacchetti con APT. Il suo
principale vantaggio è quello di poter essere utilizzato in una interfaccia
semigrafica a terminale, cui si accede invocandolo senza nessun argomento, in
tal caso si otterrà una schermata come quella illustrata in
fig.~\ref{fig:aptitude_screen}, da cui si potranno dare i vari comandi (ed
utilizzare pure un help in linea).

In generale però \texttt{aptitude} può essere usato da riga di comando in
maniera analoga ad \texttt{apt-get}, fintanto che si usano le operazioni di
base illustrate in tab.~\ref{tab:adv_pkg_aptget_options}. Il comando però non
è totalmente equivalente, infatti le opzioni \texttt{-{}-purge} e
\texttt{-{}-reinstall} non esistono e sono state trasformate in omonime
operazioni separate. Inoltre le operazioni di aggiornamento, pur mantenendo
per compatibilità lo stesso nome, sono svolte con algoritmi diversi e ad
esempio con \texttt{upgrade} pacchetti non presenti possono essere installati
per risolvere le dipendenze, e possono essere disinstallati pacchetti non
utilizzati.

Inoltre il programma consente un maggiore controllo sugli aggiornamenti, ad
esempio con l'operazione \texttt{hold} si può bloccare indefinitamente
l'aggiornamento di un pacchetto, fintanto che questo non viene sbloccata con
\texttt{unhold}. In tab.~\ref{tab:aptitude_specific_operations} si sono
riportate alcune operazioni specifiche di \texttt{aptitude}, per tutti i
dettagli (il comando è molto potente e supporta un gran numero di operazioni)
si può di nuovo consultare la pagina di manuale o il manuale utente, la cui
versione testuale è disponibile nel file
\texttt{/usr/share/doc/aptitude/README}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|l|}
    \hline
    \textbf{Operazione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{hold}   & blocca l'aggiornamento di un pacchetto.\\ 
    \texttt{unhold} & sblocca l'aggiornamento di un pacchetto.\\ 
    \texttt{purge}  & rimuove un pacchetto e le sue configurazioni.\\ 
    \texttt{reinstall}& forza la reinstallazione di un pacchetto.\\ 
    \texttt{forbid-version}& evita l'aggiornamento per una certa versione.\\ 
    \texttt{safe-upgrade}& equivalente di \texttt{upgrade}.\\ 
    \texttt{full-upgrade}& equivalente di \texttt{dist-upgrade}.\\ 
    \texttt{search}& esegue una ricerca sul database dei pacchetti.\\ 
    \texttt{show}& mostra le informazioni su un pacchetto.\\ 
    \hline
  \end{tabular}
  \caption{Principali operazioni specifiche di \texttt{aptitude}.} 
  \label{tab:aptitude_specific_operations}
\end{table}

Oltre alla gestione dell'installazione dei pacchetti \texttt{aptitude}
consente anche di eseguire delle interrogazioni sul database dei pacchetti per
ottenere delle informazioni riguardo gli stessi. In realtà a tale scopo è
presente anche un comando dedicato, \index{comando!\texttt{apt-cache}}
\texttt{apt-cache}, che presenta funzionalità più estese. Il funzionamento del
programma è simile agli altri e prevede un primo argomento che indica
l'operazione da eseguire.

Si può allora effettuare una ricerca di un testo qualunque nella descrizione
dei pacchetti con il comando \texttt{apt-cache search testo}, in cui il
secondo argomento costituisce il testo da cercare (in realtà l'argomento viene
utilizzato come espressione regolare). Si possono in questo caso passare anche
più argomenti successivi e verrà eseguita una ricerca sulla presenza di tutti
quanti. Una seconda operazione comune è \texttt{apt-cache show pacchetto} che
consente di ottenere le caratteristiche del pacchetto, secondo quanto scritto
nella sua descrizione, ad essa si affiancano altre operazioni, citate in
tab.~\ref{tab:apt-cache_operations}, che consentono di richiede informazioni
sulle dipendenze.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Operazione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{search}  & esegue una ricerca sulle descrizioni dei pacchetti
                       con le espressioni regolari passate come argomenti.\\ 
    \texttt{show}    & mostra le informazioni relative alle caratteristiche 
                       del pacchetto passato come argomento.\\ 
    \texttt{policy}  & stampa le priorità associate a ciascun pacchetto 
                       passato come argomento ed i \textit{repository} da cui
                       esso può essere ottenuto.\\ 
    \texttt{depends} & stampa la lista dei pacchetti da cui dipende il 
                       pacchetto passato come argomento (dipendenze dirette).\\ 
    \texttt{rdepends}& stampa la lista dei pacchetti che dipendono dal 
                       pacchetto passato come argomento (dipendenze inverse).\\ 
    \texttt{showpkg} & stampa la versione e tutte le informazioni riguardo
                       dipendenze dirette ed inverse del pacchetto passato
                       come argomento.\\
    \hline
  \end{tabular}
  \caption{Principali operazioni di \texttt{apt-cache}.} 
  \label{tab:apt-cache_operations}
\end{table}

Le principali operazioni di \texttt{apt-cache} sono state riassunte in
tab.~\ref{tab:apt-cache_operations}, e come al solito si può ottenere l'elenco
completo dalla pagina di manuale del comando. Fra quelle riportate vale la
pena evidenziare \texttt{apt-cache policy}, che consente di ottenere le
\textsl{priorità} delle varie versioni di un pacchetto e l'elenco dei
repository da cui esso è disponibile, perché questo ci consente di introdurre
una funzionalità molto utile di APT che viene utilizzata spesso.

Uno dei problemi che si può avere con una distribuzione è che i pacchetti
distribuiti ufficialmente dalla stessa possono non essere molto aggiornati;
questo è particolarmente comune con Debian che segue la politica di non
aggiornare mai la versione dei pacchetti presenti nella distribuzione
stabile,\footnote{la scelta non è solo di Debian, anche RedHat segue una
  politica simile con la sua RHEL, perché in ambito professionale la stabilità
  è un requisito fondamentale, e dover aggiornare le macchine ogni sei mesi è
  un grave problema, non un vantaggio.} se non per inserire correzioni di
sicurezza, riportate indietro però sulla versione del pacchetto presente nella
distribuzione. In questo modo si evita l'introduzione di eventuali nuovi
errori o cambiamenti di comportamento che si potrebbero avere in una versione
successiva, ottenendo il massimo della stabilità, a scapito però dell'uso di
funzionalità presenti nelle versioni più recenti.

Esistono però alcune situazioni in cui sono essenziali delle funzionalità
presenti soltanto nella versione più recente di un certo pacchetto; per questo
è possibile fare riferimento ad altri \textit{repository} oltre quelli
ufficiali, da cui ottenere una versione aggiornata. In particolare per Debian
è estremamente comodo il \textit{repository} di
\url{http://backports.debian.org} che contiene versioni più recenti di molti
pacchetti ricompilati per essere usati nella versione stabile senza dover
installare niente altro che il pacchetto stesso. In tal caso si tratta di
aggiungere le opportune fonti in \texttt{sources.list}, e quello che succede è
che APT installerà la versione più recente fra quella dei pacchetti
disponibili. In situazioni come queste l'uso di \texttt{apt-cache policy} è
d'aiuto per capire quale versione del pacchetto si installa e da quale
\textit{repository}.

Un ultimo aspetto importante del sistema di gestione dei pacchetti di Debian è
che, come accennato, esso fornisce, con \textit{debconf}, un meccanismo
generico per l'auto-configurazione degli stessi. Questo non solo consente di
richiedere (e memorizzare) le eventuali informazioni necessarie per la
configurazione automatica attraverso una interfaccia generica, ma fornisce
anche delle funzionalità aggiuntive, come il fatto che aggiornando un
pacchetto possa essere automaticamente aggiornata anche la sua
configurazione. 

Questo avviene soltanto se non si sono fatte modifiche manuali alla
configurazione originale, in caso contrario il sistema chiede cosa fare,
consentendo anche di visualizzare le differenze fra nuova e vecchia
configurazione; in questo modo è possibile effettuare una scelta, inoltre in
caso di cambiamento viene sempre salvata una copia del precedente file di
configurazione (come \texttt{.dpkg-old}) se si è deciso di installare il
nuovo, o del nuovo (come \texttt{.dpkg-dist}) se si è deciso di mantenere il
vecchio.

In generale le informazioni necessarie per la configurazione vengono richieste
quando si installano i pacchetti ed i relativi file di configurazione vengono
generati automaticamente, può capitare però che si voglia riconfigurare il
pacchetto in un secondo tempo. A tale scopo viene fornito il comando
\index{comando!\texttt{dpkg-reconfigure}} \texttt{dpkg-reconfigure} che
consente di ripetere questa procedura, rieseguendo anche la richiesta delle
eventuali informazioni e rigenerando la configurazione.

Il comando prende come argomento il pacchetto o i pacchetti che si vogliono
riconfigurare, o l'opzione \texttt{-a} qualora li si vogliano riconfigurare
tutti (cosa in genere non necessaria). Inoltre, dato che il sistema di
\textit{debconf} supporta un sistema di priorità delle domande che consente di
evitare quelle al di sotto della priorità scelta, che si imposta appunto con
\texttt{dpkg-reconfigure debconf}, si può usare l'opzione \texttt{-p} per
forzare l'uso di una priorità diversa. Al solito per tutti i dettagli si
consulti la pagina di manuale.

% TODO uso del pinning
% TODO trattare postinst ecc.
% TODO trattare alien

\section{La gestione di utenti e gruppi}
\label{sec:users_groups_management}

Tratteremo in questa sezione la gestione degli utenti e dei gruppi presenti
nel sistema: vedremo i comandi utilizzati per crearli, eliminarli, e
impostarne attributi e proprietà ed esamineremo le modalità con cui
configurare le procedure di accesso al sistema, l'autenticazione e l'uso delle
risorse assegnate agli utenti.


\subsection{Una visione generale}
\label{sec:user_account}

Dato che GNU/Linux è un sistema multiutente abbiamo finora dato per scontato
la presenza di utenti che potessero utilizzarlo. In realtà la questione non è
affatto così immediata. Il kernel infatti supporta la presenza di utenti e
gruppi associando a questi degli identificatori numerici che poi vengono usati
nella gestione dei processi e dei file, ma come abbiamo abbondantemente
ripetuto in sez.~\ref{sec:struct_architecture} tutta la gestione del sistema,
compresa quella che permette il riconoscimento e l'accesso agli utenti, viene
realizzata da appositi programmi. 

Questo vale in particolare anche, come accennato in 
sez.~\ref{sec:struct_sys_arch}, per quella procedura di collegamento al
sistema che porta ad avere dei processi che vengono eseguiti dal kernel per
conto di un certo utente. Perché questa sia effettuata però occorrono le
\textsl{opportune informazioni} che permettano ai vari programmi che
gestiscono la procedura (come \texttt{login}) di sapere quali utenti ci sono,
come riconoscerli e quali risorse assegnargli.

Questo ci porta ad una delle caratteristiche fondamentali di un qualunque
sistema multitutente: il concetto di \textit{account}. Come avviene per una
banca, per poter utilizzare il sistema si deve avere un ``\textsl{conto}''
presso di lui, che ci conceda l'accesso e l'uso delle risorse.  Ovviamente
perché questo accada non solo occorrerà, come accennavamo in
sez.~\ref{sec:struct_multiuser}, che un utente si identifichi
appropriatamente, ma dovranno anche essere identificate le risorse che gli si
mettono a disposizione.

Una delle parti più critiche dell'amministrazione del sistema è allora quella
che permette di creare e mantenere le informazioni relative agli
\textit{account} degli utenti presenti, che dovranno contenere sia le
informazioni necessarie all'identificazione degli stessi che quelle relative
alle risorse messe loro a disposizione.

Tradizionalmente in un sistema unix-like l'autenticazione degli utenti viene
fatta utilizzando un \textit{username}, che è il nome che il sistema associa
all'utente, ed una \textit{password} segreta la cui conoscenza serve a
dimostrare l'autenticità della propria identità. Come accennato in
sez.~\ref{sec:struct_multiuser} il sistema prevede anche la presenza di gruppi
di utenti, che a loro volta vengono identificati da altri nomi (i
\textit{groupname}). Inoltre, come visto in
sez.~\ref{sec:struct_filesystem_arch}, ogni utente ha a disposizione una home
directory per i propri file, e quando si collega al sistema gli viene messa a
disposizione una shell, la \textsl{shell di login}, come illustrato in
sez.~\ref{sec:shell_operation_modes}. Tutte queste informazioni ed altre
ancora sono quelle che vengono mantenute ed utilizzate dai programmi per la
gestione di utenti e gruppi.

Infine si tenga presente che utenti e gruppi vengono utilizzati dal sistema
non solo per gestire gli \textit{account} delle persone fisiche che utilizzano
il sistema, ma anche per associare una \textsl{identità} ad alcuni servizi. Ad
esempio molti programmi server vengono eseguiti per conto di un utente a loro
riservato, questo permette di mantenere separati i loro file rispetto a quelli
di altri servizi e di non dare loro privilegi amministrativi,\footnote{nella
  maggior parte dei casi questi, quando servono, sono garantiti solo all'avvio
  del servizio, ed eliminati non appena non sono più necessari.} aumentando la
sicurezza del sistema.

Si ricordi infatti che dal punto di vista del kernel esistono solo gli
identificatori numerici di utenti e gruppi illustrati in
sez.~\ref{sec:struct_multiuser} e che i corrispondenti nomi sono informazioni
disponibili solo in user-space, proprio per la presenza di un sistema di
gestione degli stessi, il \textit{Name Service Switch}, che vedremo meglio in
sez.~\ref{sec:base_nsswitch_conf}. Per questo che un utente sia associato ad
una persona fisica, o semplicemente utilizzato da un programma di servizio,
per il kernel è del tutto indifferente, l'unica differenza che il kernel
riconosce fra i vari utenti è quella fra l'amministratore e gli altri, e sta
ai programmi di gestione degli utenti stabilire una politica che allochi
opportunamente gli identificatori.

Nelle prime versioni di Unix tutte le informazioni relative agli utenti ed ai
gruppi presenti nel sistema erano memorizzate su due file,
\texttt{/etc/passwd} e \texttt{/etc/group}, che tratteremo meglio in
sez.~\ref{sec:cfg_user_db}.  Dato che questi, come tutti i file di
configurazione del sistema, sono file di testo, in teoria non ci sarebbe
nessuna necessità di programmi specifici per la loro gestione, visto che
possono essere modificati a mano con un qualunque editor. Questa è una cosa
che in certi casi è comunque utile saper fare, ad esempio per togliere una
password di amministratore dal sistema contenuto in un disco montato a mano
usando un sistema di recupero, poiché in quel caso i comandi andrebbero ad
operare sulla configurazione del sistema di recupero, e non di quello che si
vuole riparare.

Nei sistemi moderni però il meccanismo di gestione di utenti e gruppi è stato
completamente modularizzato attraverso sia l'uso del \textit{Name Service
  Switch} (vedi sez.~\ref{sec:base_nsswitch_conf}) che di PAM
(\textit{Pluggable Authentication Modules}, vedi sez.~\ref{sec:cfg_user_PAM}).
In questo modo è possibile mantenere le informazioni ed effettuare i relativi
controlli usando i supporti più disparati (server NIS, vari database, server
LDAP, ecc.), e quindi in generale non è più possibile andare ad effettuare le
modifiche a mano con un editor. L'uso di un supporto modulare però fa sì che
in molti casi si possano utilizzare buona parte degli stessi comandi che in
origine operavano solo sui file di testo in maniera trasparente rispetto al
meccanismo con cui sono effettivamente gestite le informazioni.



\subsection{Il database di utenti e gruppi}
\label{sec:cfg_user_db}

Nelle prime versioni di Unix tutte le informazioni relative ad utenti e gruppi
venivano mantenute in due soli file: \texttt{/etc/passwd} e
\texttt{/etc/group}. In seguito, con l'introduzione delle \textit{shadow
  password}, ne sono stati aggiunti altri due: \texttt{/etc/shadow} e
\texttt{/etc/gshadow}. Infine con l'uso di PAM (trattato in
sez.~\ref{sec:cfg_user_PAM}) e del \textit{Name Service Switch} (trattato in
sez.~\ref{sec:base_nsswitch_conf}) è divenuto possibile utilizzare i supporti
più vari. A tutt'oggi però la modalità più comune per mantenere il database
degli utenti e dei gruppi presenti su un sistema GNU/Linux resta quella di
scrivere le relative informazioni sui file di testo appena citati, che sono
quelli che tratteremo in questa sezione.

Fin dalle prime versioni di Unix la lista degli utenti viene mantenuta nel
file \index{configurazione!\texttt{/etc/passwd}} \texttt{/etc/passwd},
chiamato così perché al suo interno venivano memorizzate anche le password.
Il formato di \texttt{/etc/passwd} è molto semplice, per ogni utente deve
essere presente una riga composta da 7 campi separati dal carattere
``\texttt{:}'' e non sono ammessi né commenti né righe vuote.  Il significato
dei sette campi è il seguente:
\begin{enumerate*}
\item il nome dell'utente (l'\textit{username}).
\item password cifrata (opzionale).
\item l'\textit{user ID} (vedi sez.~\ref{sec:struct_multiuser}) dell'utente
\item il \textit{group ID} del gruppo principale dell'utente.
\item nome e cognome dell'utente ed eventuali altri campi di commento separati
  da virgole; questo campo è detto anche ``\textit{Gecos}''.\footnote{per
    maggiori informazioni sul significato di questa sigla si può consulti
    \url{http://en.wikipedia.org/wiki/Gecos}.}
\item home directory dell'utente (indicata con un pathname assoluto).
\item shell di login dell'utente.
\end{enumerate*}

Tutti i dettagli relativi al formato ed al significato dei vari campi di
\texttt{/etc/passwd}, ed in particolare a quello del \textit{Gecos}, si
trovano sulla relativa pagina di manuale, accessibile con \texttt{man 5
  passwd}. Un esempio del contenuto di questo file è il seguente:
\begin{FileExample}[label=/etc/passwd]
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:100:sync:/bin:/bin/sync
games:x:5:100:games:/usr/games:/bin/sh
man:x:6:100:man:/var/cache/man:/bin/sh
...
piccardi:x:1000:1000:Simone Piccardi,,,:/home/piccardi:/bin/bash
...
\end{FileExample}

L'elenco dei gruppi viene invece mantenuto nel file
\index{configurazione!\texttt{/etc/group}} \texttt{/etc/group}; il suo formato
è analogo a quello di \texttt{/etc/passwd}: un gruppo per linea senza commenti
e righe vuote. In però questo caso i campi presenti sono soltanto quattro,
sempre separati dal carattere ``\texttt{:}'', ed indicano rispettivamente:
\begin{enumerate*}
\item il nome del gruppo (il cosiddetto \textit{groupname}).
\item la password del gruppo (si veda sez.~\ref{sec:cmd_users}).
\item il \textit{group ID} (vedi sez.~\ref{sec:struct_multiuser}) del gruppo
\item la lista degli \textit{username} degli utenti appartenenti al gruppo,
  separati da virgole.
\end{enumerate*}

Come per \texttt{/etc/passwd} si possono trovare tutti i dettagli sul formato
ed il significato dei campi di \texttt{/etc/group} nella rispettiva pagina di
manuale, accessibile con \texttt{man group}; un esempio del contenuto di
questo file è il seguente:
\begin{FileExample}[label=/etc/group]
root:x:0:
daemon:x:1:
bin:x:2:
sys:x:3:
adm:x:4:
tty:x:5:piccardi,admin
...
piccardi:x:1000:
...
\end{FileExample}

\index{gruppo~principale|(} 
\index{gruppo~primario|(} 
\index{gruppo~ausiliario|(} 

Si noti come in \texttt{/etc/group} non vengano riportati come membri di un
gruppo gli utenti che hanno lo stesso come gruppo principale. Questa
informazione infatti viene mantenuta in \texttt{/etc/passwd}, mentre qui
vengono riportati solo gli utenti che hanno quel gruppo come gruppo
ausiliario.  Si noti inoltre come in entrambi gli esempi sia presente una
``\texttt{x}'' nel campo dedicato alla password; questo indica che sono attive
le \textit{shadow password}, su cui torneremo fra poco.

\index{gruppo~principale|)} 
\index{gruppo~primario|)}
\index{gruppo~ausiliario|)} 

In genere per modificare i dati di questi file si possono utilizzare gli
opportuni comandi di gestione, che vedremo in sez.~\ref{sec:cmd_users};
trattandosi di file di testo è comunque possibile effettuare interventi di
emergenza anche con un semplice editor.  Uno di questi potrebbe essere,
qualora si fosse persa la password di root e non si riuscisse più ad entrare
nel sistema, quello di far ripartire il computer con un CD di recupero o una
distribuzione ``\textit{live}'' e, montato il disco, togliere la
``\texttt{x}'' lasciando vuoto il campo della password. L'assenza di un campo
per la password infatti fa sì che questa non venga più
richiesta,\footnote{questo è il comportamento tradizionale, oggi la cosa viene
  controllata dal sistema di PAM (vedi sez.~\ref{sec:cfg_user_PAM}) ed in
  genere la configurazione che viene adottata dalla maggior parte delle
  distribuzioni lo consente soltanto quando si è su una console autorizzata.}
e al successivo riavvio si potrà così entrare nel sistema per ripristinarla
senza doversi autenticare.

Ovviamente, dato che la creazione di utenti e gruppi è un compito riservato
all'amministratore, entrambi i file devono appartenere a root ed essere
protetti da scrittura. Essi però devono poter essere letti da chiunque, perché
le informazioni mantenute in questi file sono quelle che vengono usate da
tutti i programmi (ad esempio anche da \texttt{ls} e \texttt{ps}) per tradurre
gli identificativi numerici del \textit{group ID} e dell'\textit{user ID}
usati dal kernel nei corrispondenti \textit{username} e \textit{groupname}.

Il fatto che questi file siano leggibili da tutti può fare legittimamente
sorgere il dubbio di come questo si possa conciliare con il fatto che vi
vengano mantenute delle password che si suppone debbano restare segrete.
Questo è possibile perché le password non sono mai memorizzate in chiaro; il
testo della password non viene scritto da nessuna parte nel sistema, quello
che viene memorizzato è solo il risultato della cifratura della password, cioè
il suo ``\textit{hash} \textsl{crittografico}'' (si ricordi quanto detto in
sez.~\ref{sec:integrity_check_cmd}).

Tutte le volte che si richiede una autenticazione quello che il sistema fa è
semplicemente ricalcolare questo valore per la password che gli si fornisce e
verificare che coincida con quello memorizzato. In realtà la procedura è
leggermente più complessa perché per evitare che a password uguali
corrispondano cifrature uguali ad esse viene aggiunto un valore casuale, detto
\textit{salt}, che serve a differenziarle in modo che due utenti non si
possano accorgere di avere la stessa password. Questo \textit{salt} viene
memorizzato insieme alla cifratura e riutilizzato nella verifica.

Dato che solo se si è fornita la password originaria si potrà riottenere lo
stesso risultato, in caso di coincidenza si è ottenuta l'autenticazione. Se il
meccanismo crittografico utilizzato è valido, e lo si reputa tale quando
qualunque metodo si possa usare per fare questa conversione inversa richiede
una quantità di calcolo equivalente a quello di provare tutte le possibili
password, si ha come conseguenza che risalire dal valore cifrato alla password
originale è praticamente impossibile, per cui il rendere leggibile
quest'ultimo non viene ritenuto un problema.

Benché l'algoritmo crittografico con cui si calcolano le password sia
piuttosto robusto, mantenere leggibili le password, anche se cifrate, espone
comunque ad un attacco a \textsl{forza bruta}, cioè alla possibilità che
qualcuno tenti davvero di provarle tutte.  L'algoritmo originale, il DES,
infatti oggi non viene più usato proprio perché prevede delle chiavi di
dimensione ridotta ed ha dei limiti sul numero di caratteri delle password
(vengono usati solo i primi 8 caratteri) che rendono molto semplice un attacco
a \textsl{forza bruta}. Per questo oggi si usano algoritmi alternativi come
MD5 che prende password di dimensioni qualsiasi e utilizza chiavi più lunghe.


Ma se quando è stato creato Unix l'eventualità di un attacco a \textsl{forza
  bruta}, dati i computer dell'epoca, era impraticabile, con la potenza dei
computer di oggi lo è molto meno. Questo anche perché esistono metodi per
precalcolare grandi numeri di chiavi e compilare delle tabelle che consentono
di ridurre notevolmente le richieste di calcolo a scapito di un maggior uso di
memoria.  Inoltre anche se oggi è diventato possibile usare algoritmi di
crittografia che rendono più difficile un attacco di questo tipo, c'è sempre
da fare i conti con la pigrizia degli utenti che tendono ad usare password
come \texttt{pippo} o \texttt{ciccio} ed anche se è possibile forzare gli
utenti ad usare password più solide (lo vedremo in
sez.~\ref{sec:cfg_user_PAM}) ma non è detto che questo sia sempre possibile.

Per cui anche se gli attacchi a forza bruta non sono praticabili, è comunque
piuttosto semplice, e ci sono programmi molto efficienti nel farlo, utilizzare
quello che si chiama un \textsl{attacco a dizionario}, in cui invece che tutte
le combinazioni possibili si provano solo quelle relative ad un dizionario di
password probabili.\footnote{per una trattazione più accurata di queste
  problematiche si può consultare \cite{SGL}.} E non giovano neanche
trucchetti come quello di scrivere le parole alla rovescia, aggiungere qualche
cifra in cima o in fondo, invertire delle lettere o mettere un ``\texttt{3}''
al posto di una ``\texttt{e}'' o un ``\texttt{1}'' al posto di una
``\texttt{i}'' o un ``\texttt{4}'' al posto di una ``\texttt{a}'', perché sono
tutti espedienti ampiamente noti, che qualunque programma decente di
``\textit{password cracking}'' applicherà alle parole del suo dizionario.

\itindbeg{shadow~password}

Per questo motivo non è molto sicuro lasciare accessibili a chiunque le
password, anche se nella loro forma cifrata, ed alcuni anni fa è stata
effettuata una completa reimplementazione dei meccanismi di gestione degli
utenti, con l'introduzione di quello che viene chiamato il sistema delle
\textit{shadow password}. Con questo nuovo sistema, oltre a spostare le
password cifrate in un file a parte non accessibile in lettura, è stato anche
possibile aggiungere una ulteriore serie di funzionalità di sicurezza.

Quando nel sistema sono abilitate le \textit{shadow password} nel secondo
campo di \texttt{/etc/passwd} ed \texttt{/etc/group} viene posta una
``\texttt{x}'', e le password cifrate vengono spostate in \texttt{/etc/shadow}
ed \texttt{/etc/gshadow}. Nei primi tempi questa era una opzione di
installazione, ma ormai sono molti anni che tutte le distribuzioni utilizzano
le \textit{shadow password} come default.  Dato che in questo caso le altre
informazioni necessarie ai programmi restano disponibili in
\texttt{/etc/passwd} ed \texttt{/etc/group} si possono proteggere questi due
nuovi file in lettura, così che solo l'amministratore possa accedervi.

Oltre alle password cifrate in \index{configurazione!\texttt{/etc/shadow}}
\texttt{/etc/shadow} sono memorizzate una serie di ulteriori informazioni che
permettono un controllo molto più dettagliato sulle modalità e le politiche di
autenticazione di un utente, come il tempo di durata di una password, la data
in cui la si è cambiata l'ultima volta, ecc. Il formato del file è analogo ai
precedenti, e prevede 9 campi (sempre separati dal carattere ``\texttt{:}'')
il cui significato è:
\begin{enumerate*}
\item il nome dell'utente (\textit{username}).
\item la password cifrata.
\item il giorno in cui la password è stata cambiata l'ultima volta (espresso
  in numero di giorni dal 1/1/1970).
\item il numero di giorni che devono passare dall'ultimo cambiamento prima che
  la password possa essere cambiata nuovamente.
\item il numero di giorni dall'ultimo cambiamento dopo i quali la password
  scade e deve essere necessariamente cambiata.
\item il numero dei giorni precedenti quello di scadenza della password in cui
  gli utenti vengono avvisati.
\item il numero dei giorni successivi a quello di scadenza della password dopo
  i quali l'utente viene disabilitato.
\item il giorno in cui l'utente viene disabilitato (espresso in numero di
  giorni dal 1/1/1970).
\item campo riservato, non viene utilizzato.
\end{enumerate*}

Al solito tutti i dettagli relativi al formato di \texttt{/etc/shadow} ed al
significato dei vari campi possono essere trovati nella relativa pagina di
manuale, un esempio del contenuto di questo file invece è il seguente:
\begin{FileExample}[label=/etc/shadow]
root:n34MlzgKs8uTM:12290:0:99999:7:::
daemon:*:11189:0:99999:7:::
bin:*:11189:0:99999:7:::
sys:*:11189:0:99999:7:::
sync:*:11189:0:99999:7:::
games:*:11189:0:99999:7:::
...
piccardi:$1$KSRp2lZ3$s9/C2ms0Ke9UTaPpQ98cv1:11189:0:99999:7:::
...
\end{FileExample}
%$

Si noti come nell'esempio per alcuni utenti nel campo della password cifrata
sia presente il carattere ``\texttt{*}'' (talvolta viene usato anche
``\texttt{!}'').  Questo è un modo, dato che una password cifrata non potrà
mai avere questo valore, di impedire che il corrispondente utente possa
autenticarsi presso il sistema, e lo si usa normalmente quando si vuole
disabilitare l'accesso ad un utente,\footnote{questo funziona soltanto se
  l'accesso prevede l'uso di una autenticazione basata sulle password, e non è
  vero se ci sono altri meccanismi di autenticazione, come ad esempio quello a
  chiavi crittografiche di SSH che tratteremo in sez.~\ref{sec:net_ssh_key}.}
o per gli utenti dei servizi di sistema che non necessitano di eseguire un
login.

Come accennato l'utilità del sistema delle \textit{shadow password} è che
questo consente anche di impostare delle politiche di gestione delle
stesse. Ad esempio si può impostare un tempo di durata massima forzando gli
utenti a non utilizzare sempre la stessa password, cosa che a lungo andare fa
aumentare le possibilità che essa venga scoperta.

Dato che anche i gruppi possono avere delle loro password, anche in questo
caso è stato previsto un secondo file non accessibile in lettura,
\index{configurazione!\texttt{/etc/gshadow}} \texttt{/etc/gshadow} in cui
poterle mantenere, insieme ad altre informazioni.  Il formato è analogo a
quello degli altri file, i campi in questo caso sono 4 ed indicano
rispettivamente:
\begin{enumerate*}
\item nome del gruppo.
\item password cifrata.
\item utenti amministratori del gruppo (lista separata da virgole).
\item utenti appartenenti al gruppo (lista separata da virgole).
\end{enumerate*}

Di nuovo si è riportato a seguire un esempio del contenuto di
\texttt{/etc/gshadow}, il cui formato, con la descrizione completa dei vari
campi, è documentato nella relativa pagina di manuale:
\begin{FileExample}[label=/etc/gshadow]
root:*::
daemon:*::
bin:*::
sys:*::
adm:*::
tty:*::piccardi,admin
...
piccardi:!::
...
\end{FileExample}


%%
%% ### OBSOLETE BEGIN ###
%% Materiale obsoleto per la conversione da verso le shadow password
%%
\ifx\obsoletesection\undefined

\relax
\else
Oggi tutte le distribuzioni installano di default le \textit{shadow password},
ma quando si hanno dei dati che originano da una situazione veramente
obsoleta, è possibile effettuare una conversione automatica dal sistema
tradizionale usando il comando \index{comando!\texttt{pwconv}}
\texttt{pwconv}.  Il comando prima rimuove da \texttt{/etc/shadow} tutte le
voci non presenti in \texttt{/etc/passwd}, poi riporta le password presenti in
esso all'interno di \texttt{/etc/shadow},\footnote{che però vengono mantenute
  cifrate nel vecchio formato; non è infatti possibile, non avendo le password
  in chiaro, eseguire una conversione delle stesse al nuovo algoritmo di
  cifratura.} ed infine sovrascrive i valori di \texttt{/etc/passwd} con una
\texttt{x}.

Inoltre \texttt{pwconv} usa i valori dei parametri \texttt{PASS\_MIN\_DAYS},
\texttt{PASS\_MAX\_DAYS} e \texttt{PASS\_WARN\_AGE} di \texttt{login.defs}
(vedi sez.~\ref{sec:cfg_login}) per impostare i rispettivi campi di
\texttt{/etc/shadow} che non esistono in \texttt{/etc/passwd}. Analogo a
\texttt{pwconv}, ma operante sui gruppi ed i relativi file \texttt{/etc/group}
e \texttt{/etc/gshadow} è \index{comando!\texttt{grpconv}} \texttt{grpconv};
essendo le password dei gruppi poco utilizzate anche questo comando non è
molto usato. 

È possibile inoltre effettuare anche la conversione inversa, tornando dalle
\textit{shadow password} al sistema tradizionale con i comandi
\index{comando!\texttt{pwunconv}} \texttt{pwunconv} e
\index{comando!\texttt{grpunconv}} \texttt{grpunconv}, in questo caso le
password verranno reinserite in \texttt{/etc/passwd} ed \texttt{/etc/group},
ma le informazioni aggiuntive (come i dati sulle scadenze delle password)
verranno persi.

%%
%% ### OBSOLETE END ###
%% Materiale obsoleto per la conversione da verso le shadow password
%%
\fi

\itindend{shadow~password}


\subsection{I comandi per la gestione di utenti e gruppi}
\label{sec:cmd_users}

Benché sia possibile inserire a mano i dati nei vari file illustrati in
sez.~\ref{sec:cfg_user_db}, in genere è opportuno utilizzare gli appositi
comandi di gestione di utenti che si incaricano di effettuare le operazioni in
maniera corretta. Il primo di questi comandi è
\index{comando!\texttt{useradd}} \texttt{useradd}, che permette di aggiungere
un nuovo utente al sistema (cioè di creare un \textit{account}). Se usato
senza opzioni il comando prende come argomento il nuovo username e si limita a
creare una voce per il nuovo utente in \texttt{/etc/passwd} e
\texttt{/etc/shadow}, inserendo dei valori di default in tutti i campi in cui
ciò è possibile, ma non imposta la password, che resta disabilitata, e non
crea la home directory.

In genere il comando assegna automaticamente al nuovo utente un \textit{user
  ID}, utilizzando il primo numero libero maggiore di tutti gli altri
\textit{user ID} già assegnati agli altri utenti, partendo comunque da un
valore minimo previsto dal sistema, che viene stabilito dalla propria
distribuzione. Il valore minimo viene controllato dalla direttiva
\texttt{UID\_MIN} di \texttt{/etc/login.defs}, (vedi
sez.~\ref{sec:cfg_login}), valori tipici sono 1000, usato da Debian e
derivate, e 500, usato da RedHat e derivate;\footnote{anche RedHat è passata a
  1000 a partire dalla versione 7 di RHEL.} i valori fra 0 e detto limite sono
usati normalmente per gli utenti corrispondenti ai servizi di sistema.  Si può
comunque impostare un valore numerico specifico indicandolo come parametro per
l'opzione \texttt{-u} del comando.

Per quanto riguarda la home directory questa viene impostata automaticamente
con il nome dell'utente aggiunto ad una base che di default è \texttt{/home}
ma si può impostare una directory qualsiasi con l'opzione \texttt{-d}, che
prende come parametro il relativo pathname assoluto. Inoltre con l'opzione
\texttt{-m} si può richiedere anche la creazione della home directory, con
tanto di creazione al suo interno di tutti i file contenuti nella directory
\texttt{/etc/skel/} (vedi sez.~\ref{sec:cfg_login}).

In teoria si può impostare una password per l'utente direttamente con
\texttt{useradd} usando l'opzione \texttt{-p}; questa però richiede come
parametro una password specificata direttamente in forma cifrata, per cui
normalmente non si usa mai questa opzione, ma si provvede ad eseguire il
comando \texttt{passwd} in un secondo tempo.

Altre opzioni comuni sono \texttt{-s}, con cui si può indicare, passando come
parametro il relativo pathname assoluto, una shell di login alternativa;
\texttt{-g} con cui si specifica il gruppo principale, indicato per nome o per
\textit{group ID}, e \texttt{-G} con cui si impostano gli eventuali altri
gruppi a cui l'utente appartiene, indicati con una lista dei rispettivi nomi
separati da virgole.

Si tenga presente però che per poter eseguire le impostazioni manuali dei
gruppi occorre che questi già esistano in \texttt{/etc/group}. Le versioni più
vecchie del programma prevedevano, non specificando niente, l'assegnazione
automatica ad un gruppo di default, indicato dalla variabile \texttt{GROUP}
nel file \texttt{/etc/default/useradd}, predisposto dalla propria
distribuzione (ad esempio su Debian e RedHat viene usato il generico gruppo
\texttt{users} con \textsl{GID} 100). Le versioni più recenti invece si curano
di creare automaticamente un gruppo con lo stesso nome scelto per l'utente, a
meno che non si specifichi l'opzione \texttt{-N} che riporta al comportamento
precedente.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-d} & imposta la home directory dell'utente.\\ 
    \texttt{-u} & specifica un valore numerico per l'\textit{user ID}.\\ 
    \texttt{-p} & imposta la password, che deve essere passata come parametro,
                  in forma cifrata.\\  
    \texttt{-s} & imposta la shell di default.\\ 
    \texttt{-g} & imposta il gruppo primario dell'utente.\\ 
    \texttt{-G} & imposta eventuali gruppi aggiuntivi.\\ 
    \texttt{-o} & permette di specificare un \textit{user ID} già esistente.\\ 
    \texttt{-e} & imposta una data di scadenza per l'account.\\ 
    \texttt{-f} & imposta dopo quanto tempo l'account viene disabilitato dopo
                  la scadenza della password.\\ 
    \hline
    \texttt{-D} & mostra i default o li cambia se invocato con \texttt{-b},
                  \texttt{-s}, \texttt{-g}, \texttt{-e}, \texttt{-f}.\\  
    \texttt{-m} & copia il contenuto di \texttt{/etc/skel/} nella home.\\
    \texttt{-b} & imposta la base da cui viene generato il valore di default
                  della home directory.\\
    \hline
  \end{tabular}
  \caption{Principali opzioni del comando \texttt{useradd}.}
  \label{tab:useradd_options}
\end{table}

Il comando inoltre consente, tramite l'opzione \texttt{-D}, di leggere o
impostare i valori di default. In tal caso non si deve specificare nessun
utente, e se usato senza opzioni il comando stamperà i valori correnti, mentre
se utilizzato con una delle opzioni \texttt{-s}, \texttt{-g}, \texttt{-e},
\texttt{-f} cambierà il default per il rispettivo valore di impostazione
(riscrivendo il contenuto di \texttt{/etc/default/useradd}).

Inoltre si può anche specificare l'opzione \texttt{-b} che indica la directory
di base da cui viene creata la home directory di default, aggiungendo al
valore passato come parametro (il valore preimpostato è \texttt{/home})
l'username dell'utente.  Le principali opzioni sono riportate in
tab.~\ref{tab:useradd_options}, comprese quelle che consentono di impostare
alcuni attributi delle \textit{shadow password}, l'elenco completo insieme a
tutti i dettagli sul funzionamento del comando sono disponibili nella pagina
di manuale accessibile con \texttt{man useradd}.

Una volta creato un utente è possibile modificarne le proprietà con il comando
\index{comando!\texttt{usermod}} \texttt{usermod}. Il comando è simile a
\texttt{useradd}, prende come argomento il nome dell'utente che si vuole
modificare e molte opzioni (quelle elencate nella prima parte di
tab.~\ref{tab:useradd_options}) sono identiche e hanno lo stesso
significato. Si tenga presente però che l'uso dell'opzione \texttt{-G}, che
permette di indicare i gruppi aggiuntivi di cui l'utente fa parte, richiede
che si passi come parametro la lista completa (sempre separata da virgole)
degli stessi.  Questo significa che se non si inseriscono nella lista anche i
gruppi di cui l'utente fa già parte, esso ne sarà rimosso. Ovviamente questo
non è molto comodo, per cui le versioni più recenti del comando supportano
l'uso dell'opzione \texttt{-a}, che consente di usare \texttt{-G} per
aggiungere l'utente al gruppo passato come argomento mantenendo inalterati la
presenza nei gruppi a cui esso già appartiene.

Infine \texttt{usermod} supporta le opzioni \texttt{-L} e \texttt{-U}, usate
rispettivamente per bloccare e sbloccare l'accesso di un utente. Il blocco
viene realizzato con l'apposizione del carattere ``\texttt{!}'' al campo
contenente la password cifrata, così da far fallire comunque l'autenticazione,
per lo sblocco il carattere viene semplicemente rimosso. Si sono riassunte le
opzioni specifiche di \texttt{usermod} in tab.~\ref{tab:usermod_options}, al
solito per i dettagli si consulti la pagina di manuale.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-l} & specifica un diverso username.\\ 
    \texttt{-U} & sblocca l'account di un utente.\\
    \texttt{-L} & blocca l'account di un utente.\\ 
    \texttt{-a} & consente di usare \texttt{-G} per aggiungere un gruppo.\\ 
    \hline
  \end{tabular}
  \caption{Opzioni specifiche del comando \texttt{usermod}.}
  \label{tab:usermod_options}
\end{table}

Per la gestione dei gruppi l'analogo di \texttt{useradd} è
\index{comando!\texttt{groupadd}} \texttt{groupadd} che permette di creare un
nuovo gruppo, passato come argomento. Il comando permette di specificare un
\textit{group ID} specifico con l'opzione \texttt{-g}, altrimenti, come per
\texttt{useradd}, viene preso il valore seguente al \textit{group ID} più alto
assegnato. Anche in questo caso, come per gli utenti, il \textsl{GID} viene
sempre scelto all'interno dell'intervallo stabilito dalle direttive di
\texttt{/etc/login.defs}, (l'argomento è trattato in dettaglio in
sez.~\ref{sec:cfg_login}).  Se il \textit{group ID} richiesto con \texttt{-g}
è già in uso il comando normalmente fallisce con un errore, se però si
aggiunge l'opzione \texttt{-o} si può forzare l'uso di un gruppo duplicato,
mentre con l'opzione \texttt{-f} si forza il successo del comando eseguendo la
scelta di un \textit{group ID} diverso da quello richiesto come avviene con il
metodo ordinario.

Infine si può impostare un cosiddetto \textsl{gruppo di sistema} con l'opzione
\texttt{-r}. Quella dei gruppi di sistema è comunque soltanto una convenzione,
per il kernel un gruppo di sistema è un gruppo come tutti gli altri, è però
invalso l'uso da parte di tutte le distribuzioni di usare valori bassi dei
\textit{group ID}, inferiori al limite iniziale usato per i gruppi degli
utenti, da assegnare ai gruppi che vengono utilizzati per l'esecuzione di
programmi che svolgono servizi nel sistema.

Analogamente a quanto avviene per gli utenti per modificare le proprietà di un
gruppo si può usare il comando \index{comando!\texttt{groupmod}}
\texttt{groupmod}, in particolare il comando permette di cambiare il
\textit{group ID} usando \texttt{-g}, supportando sempre l'opzione \texttt{-o}
per poter specificare un gruppo già assegnato, e di cambiare il nome del
gruppo con l'opzione \texttt{-n}. Al solito per l'elenco completo delle
opzioni e tutti i dettagli si consultino le pagine di manuale.

I comandi \texttt{userdel} e \texttt{groupdel} permettono invece di cancellare
rispettivamente un utente e un gruppo, da specificare come argomento. Nel caso
di \texttt{groupdel} il comando non ha nessuna opzione specifica, ma non
effettuerà la rimozione di un gruppo se questo risulta essere il gruppo
primario di un utente, in tal caso occorre prima rimuovere l'utente con
\texttt{userdel}. Si tenga conto che \texttt{userdel} si limita a cancellare
l'utente se si vuole anche rimuoverne la home directory si dovrà usare
l'opzione \texttt{-r}, ma si tenga presente che questo non assicura la
cancellazione di tutti i file di proprietà dell'utente che potrebbero essere
in altre directory diverse dalla sua home.  Inoltre il comando prima di
operare si assicura che l'utente che si vuole eliminare non sia collegato alla
macchina rifiutandosi di proseguire altrimenti,\footnote{per far questo viene
  controllato quanto riportato in \texttt{/var/log/wtmp}, si può eseguire una
  verifica invocando il comando \texttt{last} (vedi
  sez.~\ref{sec:user_sys_info}).} la cancellazione può però essere forzata con
l'opzione \texttt{-f}.

Come alternativa ai precedenti, su Debian e derivate per la creazione e
rimozione di utenti e gruppi sono presenti i comandi
\index{comando!\texttt{adduser}} \texttt{adduser},
\index{comando!\texttt{addgroup}} \texttt{addgroup},
\index{comando!\texttt{deluser}} \texttt{deluser} e
\index{comando!\texttt{delgroup}} \texttt{delgroup} che forniscono una
interfaccia più semplice.\footnote{il comando \texttt{adduser} è presente, ma
  solo come sinonimo per \texttt{useradd}, anche su RedHat e derivate.} Con
\texttt{adduser} ad esempio nella creazione dell'utente vengono richiesti pure
i dati aggiuntivi e la password dal terminale, inoltre si può aggiungere un
utente ad un gruppo semplicemente con il comando \texttt{adduser utente
  gruppo}. Nel caso della rimozione è inoltre possibile richiedere, tramite le
opportune opzioni, anche la cancellazione di tutti i file dell'utente presenti
nel sistema, e non solo quelli della sua home; al solito per i dettagli sul
funzionamento si consultino le varie pagine di manuale ad essi dedicate.

Oltre ai comandi visti finora, che operano a livello generico su utenti o
gruppi, ci sono una serie di comandi che permettono di modificare alcuni
attributi specifici. Il più importante è \index{comando!\texttt{passwd}}
\texttt{passwd}, che permette di impostare la password di un utente e tutte le
proprietà ad essa connesse.  L'utilizzo più comune è quello in cui si invoca
il comando per cambiare la propria password, nel qual caso non è necessario
nessun argomento; il comando chiederà la password corrente e poi la nuova
password per due volte (la seconda per conferma, onde evitare errori di
battitura).

Se si specifica un argomento questo indica l'utente di cui si vuole cambiare
la password, ma si tenga presente che solo l'amministratore può cambiare la
password di un altro utente, gli utenti normali possono cambiare solo la
propria e soltanto dopo essersi autenticati fornendo la vecchia. Questo non
vale per l'amministratore, che può cambiare la propria password senza dover
fornire la attuale.

\itindbeg{shadow~password}

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-x} & imposta in numero massimo di giorni per cui la password
                  rimane valida, passati i quali l'utente sarà forzato a
                  cambiarla.\\
    \texttt{-n} & imposta il numero minimo di giorni dopo il quale una
                  password può essere cambiata, l'utente non potrà modificarla
                  prima che siano passati.\\ 
    \texttt{-w} & imposta il numero di giorni per i quali l'utente viene
                  avvertito prima della scadenza della password.\\ 
    \texttt{-i} & imposta il numero massimo di giorni per cui viene 
                  accettato il login dopo che la password è scaduta, passati i
                  quali l'account sarà disabilitato.\\ 
    \texttt{-e} & fa scadere immediatamente una password, forzando così
                  l'utente a cambiarla al login successivo.\\ 
    \hline
  \end{tabular}
  \caption{Opzioni del comando \texttt{passwd} per la gestione delle
    informazioni relative alle \textit{shadow password}.}
  \label{tab:cfg_passwd}
\end{table}

Oltre alla semplice operazione di cambiamento delle password \texttt{passwd}
supporta molte altre funzionalità relative alla gestione delle stesse, ed in
particolare per l'impostazione delle varie proprietà associate al sistema
delle \textit{shadow password} (trattate in sez.~\ref{sec:cfg_user_db}). Si
sono riportate in tab.~\ref{tab:cfg_passwd} le opzioni più rilevanti insieme
al rispettivo significato, si tenga presente che esse possono essere
utilizzate solo dall'amministratore. Infine il comando permette di bloccare e
sbloccare l'uso di un account rispettivamente con le opzioni \texttt{-l} e
\texttt{-u}, mentre l'opzione \texttt{-d} consente di cancellare totalmente la
password, in tal caso però chiunque potrà entrare nel sistema conoscendo
soltanto l'username.

Per gestire le informazioni di scadenza delle password di un utente è comunque
disponibile un comando apposito, \index{comando!\texttt{chage}}
\texttt{chage}. Questo, a parte quando invocato con l'opzione \texttt{-l} che
mostra i valori attuali delle impostazioni, può essere usato solo
dall'amministratore e prende come argomento l'username dell'utente su cui si
vuole operare. Le opzioni del comando, che consentono di cambiare le varie
proprietà di scadenza delle password, sono riportate in
tab.~\ref{tab:chage_options}; per maggiori dettagli si consulti al solito la
pagina di manuale del comando.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-d} & imposta il giorno di ultimo cambiamento delle password, in
                  numero di giorni dal primo Gennaio 1970, o nel formato
                  YYYY-MM-DD (anno-mese-giorno).\\
    \texttt{-E} & imposta il giorno di scadenza dell'account, oltre il quale
                  non sarà più utilizzabile, usa lo stesso formato di
                  \texttt{-d}, il valore $-1$ elimina la data di scadenza.\\
    \texttt{-I} & imposta per quanti giorni dopo la scadenza della password
                  l'account resta accessibile prima di essere bloccato.\\
    \texttt{-m} & imposta la durata minima (in giorni) della password.\\
    \texttt{-M} & imposta la durata massima (in giorni) della password.\\
    \texttt{-W} & imposta il numero di giorni per i quali fornisce il
                  preavviso della prossima scadenza della password.\\
    \hline
  \end{tabular}
  \caption{Opzioni del comando \texttt{chage} per la gestione delle
    informazioni di scadenza delle password.}
  \label{tab:chage_options}
\end{table}

\itindend{shadow~password}

Oltre alle proprietà associate alle password ci sono altri due comandi che
consentono di modificare le altre caratteristiche degli utenti. Il primo di
questi è \index{comando!\texttt{chfn}} \texttt{chfn} che permette di cambiare
le informazioni mantenute nel campo chiamato \textit{Gecos} (vedi
sez.~\ref{sec:cfg_user_db}), in cui si scrivono il nome reale e altri dati
relativi all'utente. Un utente può modificare solo i suoi dati, e solo quelli
permessi dal parametro \texttt{CHFN\_RESTRICT} di \texttt{login.defs} (vedi
sez.~\ref{sec:cfg_login}), previa autenticazione, mentre l'amministratore può
modificare tutti i dati di un utente qualunque. Se non si specifica nulla il
comando presenta sul terminale i dati attuali richiedendo l'immissione di un
nuovo valore, si può però specificare quest'ultimo direttamente a riga di
comando come argomento per la rispettiva opzione. Per i dettagli e le singole
opzioni si consulti al solito la pagina di manuale.

Il secondo comando è \index{comando!\texttt{chsh}} \texttt{chsh}, che permette
ad un utente di cambiare la propria shell di login, impostandone una diversa
come argomento per l'opzione \texttt{-s}, se non si specifica nulla la
richiesta viene fatta in modalità interattiva sul terminale. Anche in questo
caso un utente normale può operare solo su se stesso invocando il comando
senza argomenti, e gli verrà comunque richiesta
l'autenticazione. L'amministratore invece può operare su qualunque utente
senza restrizioni, passando il relativo username come argomento.  Inoltre un
utente normale non può indicare come shell un programma qualunque, ma soltanto
una shell fra quelle elencate nel file \texttt{/etc/shells} (vedi
sez.~\ref{sec:cfg_login}).

Abbiamo accennato in sez.~\ref{sec:cfg_user_db} come, benché sia una
caratteristica sostanzialmente inutilizzata e pressoché sconosciuta, è
possibile assegnare una password anche ad un gruppo, inoltre con
l'introduzione delle \textit{shadow password} è possibile anche definirne
degli amministratori, cioè dei membri del gruppo a cui è possibile delegare la
capacità di aggiungere e rimuovere utenti dallo stesso.  Il programma che
permette di gestire tutto questo, ed in generale tutte le caratteristiche dei
gruppi, è \index{comando!\texttt{gpasswd}} \texttt{gpasswd}.

Normalmente, come si può verificare nell'estratto riportato in
sez.~\ref{sec:cfg_user_db}, i gruppi hanno una password disabilitata, vale a
dire che il secondo campo di \texttt{/etc/gshadow} è impostato ad un valore
(``\texttt{*}'' o ``\texttt{!}'') che non corrisponde a nessun hash valido.
Questo significa che possono far parte del gruppo solo gli utenti presenti
come membri dello stesso in \texttt{/etc/group},\footnote{in realtà vengono
  usati gli stessi dati presenti \texttt{/etc/gshadow}, che ha la precedenza
  in caso di differenze.}  se si imposta una password diventa invece possibile
ad altri utenti diventare membri del gruppo, fornendo la relativa password.

La password di un gruppo si può impostare con \texttt{gpasswd} passando come
argomento il nome del gruppo stesso. Il comando inoltre può essere usato per
aggiungere o rimuovere utenti da un gruppo rispettivamente con le opzioni
\texttt{-a} e \texttt{-d} (cui passare come parametro il nome
dell'utente). Infine è possibile anche rimuovere completamente la password di
un gruppo (consentendo a chiunque di diventarne parte) con l'opzione
\texttt{-r}, mentre con l'opzione \texttt{-R} si disabilita l'uso della
password, riportandosi alla situazione ordinaria.

Tutte queste operazioni possono essere compiute solo dall'amministratore di
sistema o dagli amministratori del gruppo; questi possono essere impostati
solo dall'amministratore di sistema tramite l'uso dell'opzione \texttt{-A} cui
passare una lista di utenti separati da virgole. Sempre all'amministratore di
sistema è riservato l'uso dell'opzione \texttt{-M} che consente di definire i
membri ordinari del gruppo, passati sempre come lista di utenti separata da
virgole.

Uno dei problemi che ci si trova ad affrontare con \texttt{passwd} e
\texttt{gpasswd} è che entrambi richiedono che l'immissione della password
avvenga da un terminale e non l'accettano qualora lo \textit{standard input}
sia un file o provenga da una redirezione di un comando precedente. Pertanto
non sono di uso immediato qualora li si voglia usare in uno script, ad esempio
per eseguire un cambiamento di password su un gran numero di utenti in maniera
automatica.

In teoria in casi come questo si potrebbe pensare di usare \texttt{usermod} e
\texttt{groupmod}, che consentono di impostare la password con l'opzione
\texttt{-p} ma a parte le considerazioni di sicurezza, dato che il valore
passato comparirebbe nella riga di comando, che è sempre visualizzabile
nell'uscita di \texttt{ps}, una tale opzione richiede che la password sia
passata in forma cifrata nel formato adeguato.

Per risolvere questo problema si possono usare due comandi,
\index{comando!\texttt{chpasswd}} \texttt{chpasswd} e
\index{comando!\texttt{chgpasswd}} \texttt{chgpasswd}, creati appositamente
per cambiare password rispettivamente a liste di utenti o di gruppi. Entrambi
leggono la lista delle modifiche da fare dallo \textit{standard input} che in
questo caso non è necessario sia un terminale. Il formato della lista è
analogo e prevede una riga per utente (o gruppo) divisa in due campi separati
dal carattere ``\texttt{:}'', in cui il primo campo indica l'\textit{username}
(o il \textit{groupname}) ed il secondo la password, in chiaro, che verrà
cifrata dal comando stesso.

Si tenga presente che entrambi i comandi proseguono l'esecuzione in caso di
fallimento per il cambiamento della password di un utente (o di un gruppo)
passando a quello successivo e riportando un errore solo alla fine
dell'esecuzione. Entrambi i comandi supportano l'opzione \texttt{-c} per
indicare l'algoritmo crittografico da utilizzare (uno fra DES, MD5, NONE, e
SHA256 o SHA512) e \texttt{-e} per indicare che le password vengono fornite
già cifrate sullo \textit{standard input}. Per i dettagli si consultino al
solito le pagine di manuale.


\subsection{Impersonare i ruoli di altri utenti e gruppi}
\label{sec:sudo_group_user}

Come già accennato in sez.~\ref{sec:struct_multiuser} l'architettura di un
sistema unix-like prevede fin dalla sue origini che tutti i programmi vengano
eseguiti facendo sempre riferimento ad un utente ed ai gruppi di cui questo fa
parte, ed anche come l'accesso al sistema sia vincolato al qualificarsi presso
lo stesso assumendo una certa identità, per conto della quale si potranno poi
effettuare tutte le operazioni successive.

Ci sono però dei casi in cui, pur essendosi collegati al sistema con un certo
utente, diventa necessario assumere l'identità di un altro utente per eseguire
altri compiti: il caso più classico in cui questo avviene è quello in cui si
devono compiere operazioni sul sistema come amministratore.  Ovviamente è
sempre possibile scollegarsi dal sistema e ricollegarsi come amministratore,
ma, specie se si è all'interno di una sessione grafica, questo non solo è
scomodo ma anche pericoloso, dato che non è il caso di fare girare programmi
ad interfaccia grafica con i privilegi di \textit{root}. 

Una regola d'oro per evitare guai infatti è quella di non usare mai i
privilegi di amministratore se non quando strettamente necessario per le
operazioni che si devono compiere. Per l'uso ordinario del sistema
\textit{root} non serve, ed usarlo per qualunque altro compito che non sia
l'amministrazione di sistema significa correre dei rischi inutili anche solo
per gli effetti che potrebbe avere un comando sbagliato.

Ovviamente se si è collegati si può sempre selezionare un'altra console e
rieffettuare la procedura di login per assumere l'identità dell'utente che ci
interessa, se si hanno le relative credenziali di accesso, ma per semplificare
la procedura ci vengono incontro una serie di comandi grazie ai quali diventa
possibile eseguire programmi per conto di altri utenti o altri gruppi
direttamente dalla propria sessione di lavoro. Dato che un utente normale non
può eseguire programmi per conto di altri, per far questo i suddetti comandi
sono tutti dotati di \textit{suid bit} per l'utente di amministrazione, che è
l'unico che ha questa capacità, e richiedono, a meno di non essere lanciati
dall'amministratore stesso, che chi li esegue fornisca delle opportune
credenziali di accesso (in genere una password).

% TODO (su per cosa sta ?)

Il comando classico usato per cambiare identità è \index{comando!\texttt{su}}
\texttt{su}, che in genere viene invocato senza argomenti per diventare
amministratore, (a seconda delle interpretazioni nome sta per
\textit{\textbf{s}uper \textbf{u}ser} o \textit{\textbf{s}witch
  \textbf{u}ser}). Si può comunque diventare un utente qualsiasi passando al
comando il relativo \textit{username}. Il comando richiede di autenticarsi con
la password dell'utente richiesto, a meno che non si sia già l'amministratore
nel qual caso non viene richiesta nessuna password. Questo consente
all'amministratore di \textsl{impersonare} qualunque utente senza doverne
conoscere la password.

Se non si specifica altro il comando dopo di che esegue una shell per conto
dell'utente che si è scelto di impersonare, ed è anche previsto, come ausilio
per la verifica delle operazioni, che ogni operazione eseguita con \texttt{su}
venga opportunamente registrata nel \textit{syslog}, nella \textit{facility}
\texttt{auth} (vedi sez.~\ref{sec:syslog.conf}).

Di default come effetto del comando viene lanciata la shell di login
specificata dal sesto campo della voce di \texttt{/etc/passwd} associata
all'utente che si va ad impersonare, da cui poi si potranno eseguire i comandi
per conto di questi. Si può però eseguire anche un singolo comando (sempre
all'interno di detta shell) specificandolo come parametro per l'opzione
\texttt{-c}.

Si può inoltre richiedere l'uso di una shell diversa rispetto a quella di
login, specificandola come parametro per l'opzione \texttt{-s}. Questo però è
possibile soltanto se all'utente è stata assegnata una shell elencata in
\texttt{/etc/shell}; in caso contrario, se l'utente ha quella che viene
chiamata (vedi sez.~\ref{sec:cfg_login}) una \textit{restricted shell}, a meno
che il comando non sia stato invocato dall'amministratore, l'opzione viene
ignorata.

Infine si tenga presente che anche se \texttt{su} consente di avere una shell
eseguita per conto di un altro utente la directory di lavoro e l'ambiente
restano quelli della shell da cui si era partiti; se ci si vuole trovare in
una situazione analoga a quella che avrebbe l'utente scelto dopo il suo login,
si può usare l'opzione \texttt{-l} (o anche semplicemente \texttt{-}). Si sono
riportate le principali opzioni del comando in tab.~\ref{tab:su_options}, al
solito per i dettagli e l'elenco completo si faccia riferimento alla pagina di
manuale.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-c \textsl{cmd}}  & richiede l'esecuzione del solo comando passato
                                come argomento.\\
    \texttt{-s \textsl{shell}}& richiede l'uso della shell passata come
                                argomento.\\
    \texttt{-l} o \texttt{-}  & richiede la creazione di un ambiente analogo a
                                quello risultante dopo il login dell'utente
                                richiesto.\\ 
    \hline
  \end{tabular}
  \caption{Principali opzioni del comando \texttt{su}.}
  \label{tab:su_options}
\end{table}

In sez.~\ref{sec:cfg_user_db} abbiamo detto che impostando una password su un
gruppo si può permettere ad altri utenti che non ne sono membri di farne
parte; non abbiamo però spiegato come farlo. La modalità più comune è
attraverso l'uso del comando \index{comando!\texttt{newgrp}} \texttt{newgrp}.
Il comando permette infatti di eseguire una nuova shell aggiungendo il gruppo
passato come argomento ai propri gruppi ausiliari. 

Alternativamente si può usare anche il comando \index{comando!\texttt{sg}}
\texttt{sg}, che però, in analogia con \texttt{su}, supporta l'opzione
\texttt{-c} che consente di eseguire un singolo comando con i privilegi del
nuovo gruppo.  Entrambi i comandi prendono come argomento il nome del gruppo
del quale si vogliono avere i diritti e richiedono la relativa password, ma la
password non è richiesta se i comandi vengono eseguiti dall'amministratore. Al
solito per i dettagli si consultino le rispettive pagine di manuale.

Benché \texttt{su} venga utilizzato comunemente per ottenere temporaneamente i
privilegi di amministratore (o di un altro utente) una volta che questi sono
stati ottenuti non c'è più nessuna limitazione. Esistono invece molte
situazioni in cui può tornare utile far eseguire ad un normale utente un
programma per conto dell'amministratore o di un altro utente, ma si vuole che
questi possa eseguire in questo modo solo quello specifico programma.

Per soddisfare questa esigenza esiste un apposito comando,
\index{comando!\texttt{sudo}} \texttt{sudo}, che consente di delegare
l'esecuzione per conto di altri di singoli comandi, script o programmi.  Il
programma è controllato da un apposito file di configurazione in cui si può
specificare quale programma può essere lanciato per conto di quale utente e
quali sono gli utenti cui questo è consentito. 

Per utilizzare \texttt{sudo} basta specificare come argomento il comando che
si vuole eseguire insieme alle eventuali opzioni. Se questo è consentito dalla
configurazione verrà richiesta la \textsl{propria} password, a meno che il
comando venga eseguito dall'amministratore o che si chieda un'esecuzione per
conto del proprio utente, dopo di che il comando verrà eseguito. Se non si
specifica altro il comando viene eseguito per conto dell'amministratore, ma si
può richiedere l'esecuzione per conto di un qualunque altro utente
specificando prima del comando l'opzione \texttt{-u} seguita o dall'username o
dall'UID.

Si tenga conto che una volta che ci si sia autenticati per l'esecuzione di un
comando \texttt{sudo} mantiene l'autorizzazione valida per un breve intervallo
di tempo durante il quale non è necessario fornire nuovamente la password. Il
default è di 15 minuti, ma si può impostare un valore diverso con l'opzione
\texttt{timestamp\_timeout} in \texttt{/etc/sudoers}.  In questo modo si
possono far eseguire più comandi di seguito fornendo la password una sola
volta, semplificando una eventuale sessione di lavoro. Il comando registra
comunque, sia presso il \textit{syslog} sulla \textit{facility} \texttt{auth}
che su un eventuale file specificato nella configurazione, tutte le volte che
ne viene richiesta l'esecuzione, che questa abbia successo o meno.

Un'altra funzionalità di \texttt{sudo}, che si attiva usando l'opzione
\texttt{-e} o invocando il comando come \index{comando!\texttt{sudoedit}}
\texttt{sudoedit}, è quella che consente di delegare la modifica di un singolo
file. In tal caso infatti delegare ad un utente l'uso di un editor con i
privilegi di amministratore non è una soluzione, in quanto così si
consentirebbe di modificare un file qualunque. 

Con questa opzione invece viene prima creata una copia del file passato come
argomento, sulla quale viene invocato l'editor di default dell'utente, quello
indicato dalla variabile di ambiente \texttt{EDITOR}, o quello indicato in
\texttt{/etc/sudoers}, ed una volta eseguite le modifiche sulla copia queste
vengono riportate sul file originale. Le altre principali opzioni sono
riportate in tab.~\ref{tab:sudo_options}, per l'elenco completo si consulti al
solito la pagina di manuale.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-e} & invece di lanciare un comando consente la modifica del file
                  passato come argomento, è equivalente all'invocazione del
                  comando come \texttt{sudoedit}.\\ 
    \texttt{-u \textsl{user}}& richiede l'esecuzione per conto dell'utente
                  \texttt{user} (specificato per \textit{username} o UID).\\
    \texttt{-v} & rinnova il tempo di validità della sessione all'interno
                  del quale non viene richiesta una password.\\ 
    \texttt{-S} & richiede la lettura della password dallo
                  \textit{standard input} invece che dal terminale.\\ 
    \hline
  \end{tabular}
  \caption{Principali opzioni del comando \texttt{sudo}.}
  \label{tab:sudo_options}
\end{table}

Il grande vantaggio di \texttt{sudo} è che il comando consente di realizzare
in userspace, con una enorme flessibilità, un meccanismo di delega per
specifici compiti amministrativi a singoli utenti o gruppi, senza dover
ricorrere a meccanismi di controllo di accesso più sofisticati a livello di
kernel, tanto che una distribuzione come Ubuntu ha addirittura disabilitato
l'uso di \textit{root}, usando \texttt{sudo} per assegnare all'utente che si
crea in fase di installazione la possibilità di eseguire qualunque comando con
privilegi amministrativi.

La potenza e la flessibilità di \texttt{sudo} hanno però un costo, che è
quello di una adeguata configurazione del programma stesso, che avviene
tramite il file \index{configurazione!\texttt{/etc/sudoers}}
\texttt{/etc/sudoers}. Purtroppo in questo caso la documentazione del file
stesso, disponibile nella relativa pagina di manuale, è come minimo poco
utilizzabile, gli autori infatti la hanno espressa in forma di Backus-Naur
estesa (EBNF)\footnote{la EBNF (\textit{Extended Backus-Naur Form}) è un modo
  di esprimere una sintassi generica in una forma compatta e precisa; il
  problema è appunto che essendo una forma compatta, è anche poco chiara, e
  lascia all'utilizzatore il tutt'altro che banale compito di
  \textsl{decomprimere} l'informazione in essa contenuta; il risultato è che
  ci vuole un lavoro notevole anche solo per capire le cose più elementari.}
il che ha permesso a loro di scriverla in maniera compatta e precisa,
scaricando però lo sforzo necessario per tradurla in un significato più
comprensibile sul povero utente finale, costretto ad impararsi la notazione
EBNF anche quando ne avrebbe fatto volentieri a meno.

Per questo motivo cercheremo di dare qui una descrizione imprecisa, ma
sperabilmente più intellegibile, del formato del file, che resta comunque
molto complesso. La parte principale del file è quella delle regole che
consentono di specificare quale utente può eseguire quale comando per conto di
quale altro utente e su quali macchine.

Si possono infatti assegnare regole che si applicano solo a certe macchine
all'interno di una rete, o a certe reti o a singole macchine. Tutto questo
quando si ha a che fare con una singola macchina non ha alcun significato, ma
potrebbe essere utile per usare lo stesso file di configurazione su una serie
di macchine o all'interno di una rete. In realtà questa scelta lascia molto
perplessi, visto che la complessità aggiuntiva nella sintassi di
configurazione non pare fornire vantaggi significativi rispetto al mantenere
diverse versioni del file sulle singole macchine.

Oltre a questo è inoltre possibile definire anche degli \textit{alias} per
ciascuno dei citati componenti delle regole, per raggruppare più utenti (o
comandi, o nomi di macchine) sotto una opportuna etichetta. Si possono infine
impostare dei default per le modalità di funzionamento del comando, anche
questi specificabili per gruppi di utenti, macchine o comandi.

Al solito le righe che iniziano per ``\texttt{\#}'' vengono considerate
commenti, e le righe vuote vengono ignorate, inoltre si possono scrivere
regole o \textit{alias} su più righe terminando ciascuna con il carattere
``\texttt{\bslash}'' per indicare di proseguire sulla seguente. La sintassi di
base di una regola è nella forma:
\begin{Example}
utente ALL = (altroutente) /path/comando, /path/comando
\end{Example}

Una regola viene espressa come una serie di componenti; il primo componente,
specificato all'inizio della riga, identifica l'utente che è abilitato ad
usare \texttt{sudo} per eseguire i comandi previsti nella stessa; questo primo
componente può essere un singolo username, come nel precedente esempio, o il
nome di un gruppo preceduto dal carattere ``\texttt{\%}'', che consentirà
l'uso della regola a tutti i membri del gruppo stesso, o un \textit{alias},
con il quale si possono specificare liste di utenti, gruppi e altri
\textit{alias}. Si può altresì usare la parola chiave \texttt{ALL}, che
significa qualunque utente.

Il secondo componente, separato dal primo da uno o più spazi, nel precedente
esempio è specificato con la parola chiave \texttt{ALL}, il cui significato è
ovvio. Questo componente servirebbe ad indicare la macchina o l'elenco di
macchine, o la rete, ecc. su cui la regola è attiva, ma siccome faremo sempre
riferimento ad una configurazione che vogliamo sia effettiva sulla macchina su
cui la installiamo useremo sempre questo valore con cui si garantisce un
accesso valido su qualunque macchina. Se si hanno esigenze diverse su macchine
diverse si potranno sempre usare dei file \texttt{/etc/sudoers} contenenti
regole diverse, o studiarsi la sintassi completa delle modalità con cui si
indicano i nomi delle macchine.

Il terzo componente, separato dal secondo dal carattere uguale, nel caso
dell'esempio riporta la specificazione, messa fra parentesi tonde, dell'utente
per conto del quale si potranno eseguire i comandi indicati nelle componenti
successive. Questo componente è opzionale, e può essere omesso, nel qual caso
l'esecuzione verrà fatta per conto dell'amministratore. L'utente può essere
indicato sia per username, come nell'esempio, che per UID (con l'indicazione
del relativo valore numerico preceduto dal carattere ``\texttt{\#}''), che con
il nome di un gruppo (anche qui preceduto dal carattere ``\texttt{\%}'') nel
qual caso si potranno usare i comandi per conto degli utenti membri del detto
gruppo ed infine anche con un \textit{alias} o con la parola chiave
\texttt{ALL} che consente l'esecuzione per conto di qualunque utente.

Al terzo componente segue, separato da spazio, il comando di cui si vuole
consentire l'esecuzione; se ne può anche specificare più di uno, separandoli
con delle virgole. Anche qui vale la parola chiave \texttt{ALL} per indicare
un comando qualsiasi, inoltre si può usare il valore riservato
\texttt{sudoedit} che serve ad indicare che si sta abilitando la modifica di
un file (da indicare come argomento) e non l'esecuzione di un comando.

I comandi devono essere specificati con un pathname assoluto al relativo
programma, ma si possono usare le \textit{wildcard} del \textit{filename
  globbing} per fare selezioni multiple. Se non si specifica altro essi
potranno essere usati con qualunque argomento, si possono però specificare
anche opzioni ed argomenti e \texttt{sudo} consentirà l'esecuzione del comando
soltanto con quelle opzioni e quegli argomenti, ma in tal caso si tenga
presente che i caratteri usati nella specificazione delle regole, come
``\texttt{:}'', ``\texttt{=}'', ``\texttt{,}'', ``\texttt{\bslash}'' dovranno
essere adeguatamente protetti con un ``\texttt{\bslash}'' se presenti nelle
opzioni o negli argomenti del comando stesso. Infine se non si vuole che
vengano usati argomenti si dovrà far seguire al comando la stringa vuota
espressa con \verb|""|.

La sintassi delle regole viene ulteriormente complicata dal fatto che è
possibile esprimere più blocchi dei componenti successivi al primo separandoli
con il carattere ``\texttt{:}'', così da avere una regola che indica comandi
diversi eseguiti per conto di utenti o su macchine diverse; ma di nuovo in
casi come questi è più semplice e chiaro scrivere due regole separate
piuttosto che usare una sintassi complessa e poco leggibile.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Tag} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{NOPASSWD}& evita che \texttt{sudo} richieda l'autenticazione
                       dell'utente che intende eseguire il comando.\\ 
    \texttt{PASSWD}  & rimuove l'effetto di un precedente \texttt{NOPASSWD}.\\ 
    \texttt{SETENV}  & vengono mantenute nell'esecuzione le variabili di
                       ambiente presenti nella shell del chiamante, evitando
                       le eventuali restrizioni imposte nella configurazione
                       di default.\\
    \texttt{NOSETENV}& rimuove l'effetto di un precedente \texttt{SETENV}.\\
    \texttt{EXEC}    & evita che un comando possa lanciare al suo interno
                       altri programmi (ad esempio che dall'interno di
                       \texttt{vi} si possa eseguire una shell).\\ 
    \texttt{NOEXEC}  & rimuove l'effetto di un precedente \texttt{EXEC}.\\ 
    \hline
  \end{tabular}
  \caption{I tag per le indicazioni dei comandi in \texttt{/etc/sudoers}.}
  \label{tab:sudoers_tag}
\end{table}

Inoltre nello specificare un comando sono disponibili alcuni \textit{tag} che
consentono di controllarne le modalità di esecuzione, questi vengono
specificati indicandoli prima del comando a cui si applicano seguiti dal
carattere ``\texttt{:}''; una volta specificati valgono anche per i comandi
successivi nella regola, a meno che l'indicazione non venga soprascritta da
un'altra specificazione. L'elenco dei \textit{tag} ed il relativo significato
è illustrato in tab.~\ref{tab:sudoers_tag}.

Come accennato una delle funzionalità presenti in \texttt{/etc/sudoers} è
quella che consente la creazione di \textit{alias} che permettono di esprimere
in maniera più sintetica gruppi di utenti, o di macchine o liste di comandi;
gli \textit{alias} sono espressi nella forma di assegnazione di una stringa
identificativa al rispettivo valore, preceduta da una delle direttive di
definizione riportate in tab.~\ref{tab:sudoers_alias}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Direttiva} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{User\_Alias} & Un \textit{alias} utilizzabile per indicare gli
                           utenti che possono eseguire un certo comando, prende
                           come argomenti \textit{username}, \textit{groupname}
                           (preceduti da ``\texttt{\%}'') o altri alias.\\ 
    \texttt{Host\_Alias} & Un \textit{alias} utilizzabile per indicare una
                           lista di macchine o reti.\\ 
    \texttt{Runas\_Alias}& Un \textit{alias} utilizzabile per indicare gli
                           utenti per dei quali si può eseguire un certo
                           comando, prende come argomenti \textit{username},
                           UID (preceduti da ``\texttt{\#}''),
                           \textit{groupname}  (preceduti da ``\texttt{\%}'') o
                           altri alias.\\ 
    \texttt{Cmd\_Alias}  & Un \textit{alias} utilizzabile per indicare una
                           lista di comandi.\\ 
    \hline
  \end{tabular}
  \caption{Le direttive per la creazione di alias in \texttt{/etc/sudoers}.}
  \label{tab:sudoers_alias}
\end{table}

Infine tutta una serie di proprietà generali concernenti le modalità di
funzionamento di \texttt{sudo}, come il tempo per il quale non viene richiesta
nuovamente una password dopo essersi autenticati, possono essere impostate
tramite la direttiva \texttt{Defaults}. Questa prende come argomenti una serie
di nomi di opzioni che identificano le suddette proprietà da configurare,
separate da virgole. La sintassi prevede che l'impostazione venga effettuata
in forma di assegnazione di un valore al nome dell'opzione, ad eccezione del
caso di opzioni che hanno valore logico, nel qual caso basta citare l'opzione
per attivarla o farla precedere da un ``\texttt{!}'' per disattivarla.  A
complicare l'impostazione si aggiunge il fatto che si possono definire delle
impostazioni di default per singoli gruppi di utenti, macchine e comandi, in
una forma che non tratteremo, si consulti nel caso la pagina di manuale,
facendo riferimento agli esempi.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{env\_reset}& valore logico; di default a \texttt{on}, richiede la
                         ripulitura dell'ambiente lasciando definite soltanto
                         le variabili \texttt{LOGNAME}, \texttt{SHELL},
                         \texttt{USER}, \texttt{USERNAME} e le eventuali
                         \texttt{SUDO\_*}.\\  
    \texttt{env\_keep} & stringa; nella forma di lista di nomi separati da  
                         virgole, imposta l'elenco delle variabili di ambiente
                         che vengono preservate oltre a quelle di
                         \texttt{env\_reset}.\\ 
    \texttt{setenv}    & valore logico; di default a \texttt{off}, richiede
                         che tutte le variabili di ambiente vengano
                         preservate.\\
%    \texttt{noexec}    & .\\ 
    \texttt{passwd\_tries}& valore numerico; imposta il numero di tentativi di
                         immissione delle password.\\ 
    \texttt{timestamp\_timeout}& valore numerico; imposta il tempo, in minuti,
                         per cui \texttt{sudo} ritiene la sessione valida e non
                         richiede la password.\\ 
    \texttt{editor}    & stringa; nella forma di lista di nomi separati da
                         virgole, imposta la lista di editor che possono essere
                         usati con \texttt{visudo}.\\ 
%    \texttt{lecture}   & .\\ 
    \texttt{syslog}    & imposta la \textit{facility} del \textit{syslog} su
                         cui mandare i messaggi, il default è
                         \texttt{authpriv}.\\
    \hline
  \end{tabular}
  \caption{Le principali opzioni per i default di \texttt{/etc/sudoers}.}
  \label{tab:sudoers_defaults_options}
\end{table}

Come citato le opzioni possono avere valori numerico, testuale o logico, a
seconda del tipo di funzionalità che controllano; in generale non è necessario
specificare nessuna opzione, in quando i default hanno valori ragionevoli. Una
delle opzioni più importanti è l'opzione logica \texttt{env\_reset}, che
richiede la ripulitura dell'ambiente passato al comando.\footnote{su Debian è
  l'unica opzione che viene impostata esplicitamente
  nell'\texttt{/etc/sudoers} installato di default, su RedHat oltre a questa
  viene usata anche \texttt{env\_keep}, le versioni recenti del comando
  comunque tengono attiva questa opzione.} Questo viene fatto per evitare
possibili abusi che potrebbero avvenire sfruttando le variabili di ambiente:
si potrebbe ad esempio definire \texttt{LD\_LIBRARY\_PATH} (vedi
sez.~\ref{sec:cfg_dyn_lib}) per fare usare ad un programma delle librerie
\textsl{opportunamente} modificate, per far eseguire ad un programma delle
operazioni non troppo benevole.

Si può controllare con maggiore dettaglio l'ambiente passato al comando
utilizzando anche l'opzione \texttt{env\_keep}, che prende come valore la
lista, separata da virgole, delle variabili di ambiente che possono essere
mantenute nell'esecuzione del comando. Se invece si vuole preservare
completamente l'ambiente si può usare l'opzione \texttt{setenv}. In
tab.~\ref{tab:sudoers_defaults_options} si sono riportate le opzioni
principali, al solito per l'elenco completo si consulti la pagina di manuale.

Come esempio di configurazione che illustra la sintassi del file riportiamo il
contenuto di un \texttt{/etc/sudoers} che consente l'accesso amministrativo
agli utenti del gruppo \texttt{admin} (secondo l'approccio usato da Ubuntu),
mentre consente all'utente \texttt{webmaster} di riavviare i servizi di Apache
con l'uso del comando \texttt{apachectl}:
\begin{FileExample}[label=/etc/sudoers]
# /etc/sudoers
#
# This file MUST be edited with the 'visudo' command as root.
#
# See the man page for details on how to write a sudoers file.
#
Defaults	env_reset

User_Alias   WEBMASTER = webmaster
Cmnd_Alias   APACHECTL = /usr/sbin/apachectl

# User privilege specification
root         ALL = (ALL) ALL
%admin       ALL = (ALL) ALL
WEBMASTER    ALL = NOPASSWD: APACHECTL
\end{FileExample}
dove si sono usati (anche se nel caso sono del tutto superflui) due alias per
definire l'utente ed il comando da far eseguire per il controllo del demone di
Apache.

In questo file sono presenti tre regole, che illustrano abbastanza bene le
sintassi più comuni. Anzitutto si noti che per tutte quante viene usata la
indicazione generica ``\texttt{ALL =}'' che rende la regola valida su
qualunque macchina. La prima si applica ad un singolo utente (nel caso
l'amministratore) e la seconda ai membri del gruppo \texttt{admin} ma i
permessi sono identici, con \texttt{(ALL)} si consente di impersonare
qualunque utente, e con il successivo \texttt{ALL} di usare qualunque
comando. La terza regola usa invece un \textit{alias} per indicare l'utente
precedentemente definito a cui consente l'uso del comando \texttt{apachectl}
(anch'esso definito in un \textit{alias}) con privilegi di amministratore (si
noti che non c'è una indicazione dell'utente da usare per l'esecuzione del
programma), inoltre avendo usato il \textit{tag} \texttt{NOPASSWD} non verrà
neanche richiesta una password.

Infine si tenga presente che benché sia possibile eseguire la modifica
direttamente, la modalità più corretta per effettuare una riconfigurazione di
\texttt{sudo} è quella di usare il comando \index{comando!\texttt{visudo}}
\texttt{visudo} che consente di chiamare un editor per modificare
\texttt{/etc/sudoers} in maniera sicura.  Il programma infatti evita che si
possano effettuare modifiche simultanee (bloccando l'accesso al file se è in
corso l'uso da parte di qualcun altro) e prima di salvare la nuova versione
esegue un controllo di base, per evitare errori.



\subsection{Le configurazioni della gestione degli utenti e degli accessi}
\label{sec:cfg_login}


In sez.~\ref{sec:cfg_user_db} abbiamo trattato i file in cui classicamente
vengono mantenuti i dati di utenti e gruppi, mentre in
sez.~\ref{sec:cmd_users} abbiamo visto i comandi che consentono di gestirli;
ci restano da trattare tutti quei file di configurazione che controllano da
una parte le modalità con cui si creano utenti e gruppi e dall'altra le
modalità con cui questi accedono al sistema.

Agli albori di Unix l'unica procedura per collegarsi al sistema era quella del
login da terminale che, come accennato in sez.~\ref{sec:struct_job_control}, è
gestita dai due programmi \texttt{getty} e \texttt{login}.  Le modalità con
cui questi programmi (ed in particolare il secondo) garantiscono l'accesso
vengono impostate attraverso una serie di file di configurazione, che sono
quelli che tratteremo in questa sezione. In realtà al giorno d'oggi tutte le
distribuzioni usano i \textit{Pluggable Authentication Modules} (PAM, che
tratteremo in sez.~\ref{sec:cfg_user_PAM}), e buona parte dei file di
configurazione che un tempo venivano usati direttamente da \texttt{login}
adesso vengono utilizzati attraverso in modo generico con questa libreria, che
ne consente l'uso a qualunque programma abbia necessità di gestire l'accesso
al sistema.

Il primo file che prendiamo in considerazione è
\index{configurazione!\texttt{/etc/issue}} \texttt{/etc/issue}, che contiene
il messaggio di presenza stampato sui terminali prima dell'accesso
dell'utente. Questo file viene usato da \texttt{getty} per essere stampato sul
terminale prima della stringa ``\texttt{login: }'' dopo la quale viene
richiesto l'username; è possibile modificarlo in modo da personalizzare la
schermata di accesso al sistema.

Il contenuto del file viene stampato integralmente, ma si possono inserire,
attraverso l'uso del carattere ``\texttt{\bslash}'', delle direttive che
permettono di stampare alcune informazioni dinamiche; ad esempio con
``\texttt{\bslash s}'' si inserisce automaticamente il nome del sistema
operativo, con ``\texttt{\bslash l}'' il nome del terminale, con
``\texttt{\bslash n}'' il nome della macchina. I principali valori sono
riportati in tab.~\ref{tab:cfg_issue}, mentre l'elenco completo è riportato
nella pagina di manuale di \texttt{getty}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|l|}
    \hline
    \textbf{Carattere} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{\bslash d} & data completa.\\ 
    \texttt{\bslash l} & nome del terminale.\\ 
    \texttt{\bslash m} & architettura (i486, PPC, ecc.).\\ 
    \texttt{\bslash n} & nome della macchina (\textit{hostname}).\\  
    \texttt{\bslash r} & versione del kernel.\\ 
    \texttt{\bslash s} & nome del sistema (Debian, RedHat, ecc).\\ 
    \texttt{\bslash t} & ora del giorno.\\ 
    \hline
  \end{tabular}
  \caption{Principali caratteri di estensione per \texttt{/etc/issue}.}
  \label{tab:cfg_issue}
\end{table}

Analogo a \texttt{/etc/issue} è \index{configurazione!\texttt{/etc/issue.net}}
\texttt{/etc/issue.net}, che viene usato al suo posto quando il collegamento
viene effettuato via rete con \texttt{telnet}; si tenga conto che questo vale
solo per un login remoto eseguito con \texttt{telnet}, se invece si usa
\texttt{ssh} (vedi sez.~\ref{sec:net_ssh}) detti file normalmente vengono
ignorati.

Un secondo file utilizzato all'ingresso del sistema, questa volta quando il
login è stato completato, è \index{configurazione!\texttt{/etc/motd}}
\texttt{/etc/motd} che contiene il messaggio di benvenuto mostrato a tutti gli
utenti che si sono collegati con successo. Il nome del file sta per
\textit{message of the day}, e scrivere un messaggio in questo file è una
modalità veloce per mandare un avviso a tutti gli utenti che entrano nel
sistema dall'interfaccia a riga di comando.  Al contrario del precedente
questo file viene gestito da PAM con il modulo \texttt{pam\_motd.so}, per cui
può essere utilizzato non solo sul collegamento da terminale, ma anche da
tutti i programmi che consentono l'accesso al sistema, come \texttt{ssh} (vedi
sez.~\ref{sec:net_ssh}).

Un altro file di controllo della procedura di \textit{login} è
\index{configurazione!\texttt{/etc/securetty}} \texttt{/etc/securetty}.
Questo file contiene la lista delle \textit{console} da cui si può collegare
l'amministratore di sistema (cioè l'utente \textit{root}).  Viene usato dal
programma \texttt{login}, anzi per essere precisi dal modulo di PAM
\texttt{pam\_securetty.so} (vedi sez.~\ref{sec:cfg_user_PAM}), che legge da
esso i nomi dei dispositivi di terminale dai quali è consentito l'accesso.  Un
esempio di questo file (preso da una Debian Squeeze) è il seguente:
\begin{FileExample}[label=/etc/securetty]
console
vc/1
vc/2
...
tty1
tty2
...
\end{FileExample}

Il formato del file prevede che ogni linea definisca un nome di dispositivo di
un terminale sul quale è possibile il login, le linee vuote o che iniziano per
``\texttt{\#}'' vengono ignorate. La pagina di manuale fornisce una
descrizione completa. Dato che i terminali virtuali associati alle connessioni
di rete usualmente non sono indicati in questo file, normalmente non è
possibile utilizzare un programma come \texttt{telnet} (vedi
sez.~\ref{sec:net_telnet}) per collegarsi da remoto come
amministratore. Benché sia possibile consentirlo aggiungendo una riga al
contenuto appena illustrato, questo non è assolutamente una buona idea per cui
se proprio volete farlo dovrete studiarvelo da soli.\footnote{in generale non
  è comunque una buona idea neanche quella di usare \texttt{telnet}, quindi è
  meglio se proprio lasciate perdere completamente la cosa.}

Quando si vuole bloccare temporaneamente l'accesso al sistema degli utenti
ordinari, l'amministratore può creare il file \texttt{/etc/nologin}. Questo
non è propriamente un file di configurazione, dato che il suo contenuto è
ininfluente, la sua presenza serve solo a dire alla procedura di collegamento
al sistema che solo l'amministratore può entrare. Dato che anche l'effetto di
questo file viene gestito con PAM, ed in particolare con il modulo
\texttt{pam\_nologin.so} (vedi sez.~\ref{sec:cfg_user_PAM}), l'accesso può
essere bloccato in generale, anche dall'interfaccia grafica.  La sua rimozione
ripristinerà l'accesso per tutti gli utenti.

Oltre a quelli appena citati esistono vari altri file che consentono di
controllare le modalità della procedura per l'accesso al sistema ed in
particolare controllare alcune risorse assegnate agli utenti, oggi tutto
questo viene gestito attraverso PAM per cui rimandiamo la trattazione di
questi aspetti più avanzati alla sez.~\ref{sec:cfg_user_PAM}.

Tratteremo però qui \index{configurazione!\texttt{/etc/login.defs}}
\texttt{/etc/login.defs}, che un tempo era il principale file deputato alla
configurazione della procedura di \textit{login}, e conteneva anche le
impostazioni di \texttt{login} per controllare le modalità di autenticazione
ed accesso, come il numero di possibili errori nel fornire la password, o il
tempo per cui si attende la sua immissione.  

Come accennato nelle distribuzioni recenti tutto quello che riguarda
l'autenticazione dell'utente e la gestione della sessione di lavoro viene
gestito tramite PAM, per cui \texttt{login} non fa più alcun uso di questo
file, anche se spesso vi si trovano riferimenti a direttive obsolete ormai non
più utilizzate.  Esso però resta come file di configurazione dell'intero
sistema di gestione degli utenti, ed in particolare viene utilizzato per la
configurazione di parametri usati dai programmi di gestione trattati in
sez.~\ref{sec:cmd_users}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{10cm}|}
    \hline
    \textbf{Parametro} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{CHFN\_RESTRICT} & indica quali campi del \textit{Gecos} possono
                              essere cambiati con \texttt{chfn} da un utente
                              ordinario, indicati con una lettera
                              identificativa, per i dettagli si consulti la
                              pagina di manuale.\\ 
    \texttt{GID\_MAX}       & imposta il valore massimo del \textit{group ID}
                              assegnabile coi comandi \texttt{useradd} e
                              \texttt{groupadd}.\\
    \texttt{GID\_MIN}       & imposta il valore minimo del \textit{group ID}
                              assegnabile coi comandi \texttt{useradd} e
                              \texttt{groupadd}.\\ 
    \texttt{PASS\_MAX\_DAYS}& imposta il valore di default per la massima
                              durata della validità di una password, usato al
                              momento della creazione dell'utente.\\  
    \texttt{PASS\_MIN\_DAYS}& imposta il valore di default per la minima
                              durata della validità di una password,
                              usato al momento della creazione dell'utente.\\ 
    \texttt{PASS\_WARN\_AGE}& imposta il valore di default per il numero di
                              giorni precedenti la scadenza di una password
                              per i quali viene mandato un avviso, usato al
                              momento della creazione dell'utente.\\
    \texttt{UID\_MAX}       & imposta il valore massimo dell'\textit{user ID}
                              assegnabile col comando \texttt{useradd}.\\ 
    \texttt{UID\_MIN}       & imposta il valore minimo dell'\textit{user ID}
                              assegnabile col comando \texttt{useradd}.\\ 
    \texttt{MAIL\_DIR}      & indica la directory della posta dell'utente,
                              viene usato dai comandi di gestione dell'utente
                              per creare, spostare o rimuovere la posta dello
                              stesso.\\ 
    \texttt{USERDEL\_CMD}   & se definito indica il comando che verrà eseguito
                              alla rimozione di un utente (ad esempio per
                              compiere controlli aggiuntivi come la rimozione
                              di eventuali stampe sospese).\\ 
    \hline
  \end{tabular}
  \caption{Principali parametri di configurazione di
    \texttt{/etc/login.defs}.} 
  \label{tab:cfg_login_defs}
\end{table}

Il formato di \texttt{login.defs} è molto semplice, al solito sono considerati
commenti le righe che iniziano per ``\texttt{\#}'' ed ignorate le righe vuote.
Ciascuna riga contiene l'assegnazione di un parametro di configurazione, fatta
nella forma di un nome che lo identifica seguito dal valore da assegnargli,
separato da uno o più spazi. A seconda del parametro il valore può essere una
stringa, un numero, o un valore logico (specificato nella forma \texttt{yes} o
\texttt{no}). 

Abbiamo già accennato ad alcuni di questi parametri, come \texttt{UID\_MIN} e
\texttt{UID\_MAX} in sez.~\ref{sec:cmd_users}, un elenco di quelli più
rilevanti è stato riportato in tab.~\ref{tab:cfg_login_defs}, l'elenco
completo si trova nella pagina di manuale associata al file. Un esempio del
contenuto di questo file, estratto della versione installata su una CentOS
5.2, è il seguente:
\begin{FileExample}[label=/etc/login.defs]
MAIL_DIR	/var/spool/mail
PASS_MAX_DAYS	99999
PASS_MIN_DAYS   0
PASS_MIN_LEN    5
PASS_WARN_AGE   7
UID_MIN	        500
UID_MAX	        60000
GID_MIN	        500
GID_MAX	        60000
...
\end{FileExample}

Si tenga presente infine che se si fa riferimento al contenuto effettivo di
\texttt{/etc/login.defs} vi si potranno trovar definiti anche una gran
quantità di parametri non citati nella pagina di manuale; alcuni di questi
sono semplicemente obsoleti e non hanno nessun effetto in quanto gran parte
delle impostazioni presenti un tempo, ed in particolare quelle usate da
programmi come \texttt{login}, \texttt{passwd} e \texttt{su}, viene oggi
effettuata attraverso i moduli di PAM. Alcuni di questi però, anche a seconda
di come sono stati costruiti i comandi citati, potrebbero essere tenuti in
conto come valori di riserva qualora le impostazioni eseguite con PAM non
funzionassero.

\index{shell!di~login|(}

Un altro file utilizzato dal sistema di gestione degli utenti è
\index{configurazione!\texttt{/etc/shells}} \texttt{/etc/shells}, che contiene
la lista delle shell valide che l'utente può selezionare con il comando
\texttt{chsh} (vedi sez.~\ref{sec:cmd_users}). Il file utilizza il solito
formato in cui le righe inizianti per ``\texttt{\#}'' sono considerate
commenti e le righe vuote sono ignorate.  Ogni riga non vuota contiene un solo
campo che specifica il pathname completo del programma che può essere usato
come shell. Un utente che voglia cambiare la propria shell di default potrà
usare solo una shell fra quelle che sono indicate in questo file. In questo
modo l'amministratore può lasciare all'utente la libertà di modificare la
propria shell di login, restringendola però alle shell autorizzate.

Il file però ha degli effetti anche sul funzionamento di altri programmi, in
particolare viene usato per verificare se un utente è un utente ordinario con
accesso al sistema, sulla base della presenza della sua shell di login, che si
ricordi è quella definita nell'ultimo campo di \texttt{/etc/passwd} (vedi
sez.~\ref{sec:cfg_user_db}), in questo file.

\index{shell!restricted|(}

Si dice infatti che un utente è dotato di una \textit{restricted shell} quando
la sua shell di login non è fra quelle elencate in
\texttt{/etc/shells}.\footnote{si rammenti che questo è un concetto diverso
  rispetto alla modalità ristretta della \texttt{bash} vista in
  sez.~\ref{sec:shell_operation_modes}, anche se in inglese anche questa viene
  chiamata allo stesso modo.}  Sono esempi tipici di utenti associati ad una
\textit{restricted shell} quelli utilizzati per i servizi di sistema,come gli
utenti associati ai servizi di fornitura di pagine web o gestione della posta
elettronica, che spesso hanno come shell programmi come \texttt{/bin/false}
(vedi sez.~\ref{sec:shell_scripting}) o \index{comando!\texttt{nologin}}
\texttt{/usr/bin/nologin} che non consentono comunque di collegarsi al
sistema. Quest'ultimo è un semplice programma che stampa un messaggio dicendo
che l'utente non è utilizzabile e ritorna un codice di errore;
\texttt{nologin} è stato creato apposta per essere usato come
\textit{restricted shell} da assegnare agli utenti di servizio che non
necessitano di avere un accesso al sistema.

La presenza di una \textit{restricted shell} in \texttt{/etc/passwd} viene
usata da vari programmi per modificare il proprio comportamento. Ad esempio
alcuni server FTP rifiutano l'accesso ad username corrispondenti ad utenti che
non hanno una shell valida fra quelle elencate in \texttt{/etc/shells},
mentre, come accennato in sez.~\ref{sec:sudo_group_user}, \texttt{su} si
rifiuta di eseguire un comando per conto di un altro utente usando una shell
diversa da quella di login se questi ha una \textit{restricted shell}.

\index{shell!restricted|)}

Si tenga conto comunque che qualora l'utente abbia comunque un accesso ad una
shell l'impedirgli di cambiare la shell di login al di fuori di quelle di
\texttt{/etc/shells} non significa che gli si può impedire di usare un'altra
shell, questi infatti potrà comunque installare nella propria home directory
un'altra shell ed usare quella al posto della shell di login, lanciandola
semplicemente come un qualunque altro programma; non potrà però cambiare
quella con cui entra nel sistema al login.

\index{shell!di~login|)}

Infine, come ultimo argomento relativo alle configurazioni che attengono alla
gestione degli utenti, dobbiamo trattare la directory
\index{configurazione!\texttt{/etc/skel}} \texttt{/etc/skel/}. Come accennato
in sez.~\ref{sec:cmd_users}, nella creazione di un nuovo utente è possibile
richiedere la creazione della sua home directory; questa può anche essere
creata con uno \textsl{scheletro} di contenuti, che siano gli stessi per ogni
nuovo utente. Con questo si può far sì ad esempio che alcune impostazioni
personali di programmi di uso comune\footnote{si ricordi che, come accennato
  in sez.~\ref{sec:cfg_general}, molti programmi consentono all'utente di
  usare configurazioni personalizzate con dei file nella propria home.} siano
predefinite ed assegnate in modo uniforme alla creazione di ogni nuovo utente.

La directory \texttt{/etc/skel/}, come il nome stesso suggerisce, è quella che
contiene questo scheletro. Tutti i file e le directory che si vuole siano
creati nella home directory dei nuovi utenti possono essere messi in questa
directory. Tutti i file presenti in \texttt{/etc/skel/} saranno
automaticamente copiati nella relativa home alla creazione di ogni nuovo
utente, i permessi dei file verranno mantenuti, mentre la proprietà degli
stessi verrà assegnata al nuovo utente ed al suo gruppo principale.

Il contenuto tipico di questa directory sono gli scheletri dei file di
personalizzazione della shell degli utenti: ad esempio nel caso di Debian
Squeeze il contenuto di default prevede ad esempio i file \texttt{.bashrc},
\texttt{.profile}, \texttt{.bash\_logout}, ma è possibile spingersi oltre ed
inserire al suo interno anche altre configurazioni, ad esempio CentOS vi crea
anche lo scheletro delle directory \texttt{.kde} e \texttt{.mozilla}.


\subsection{Il \textit{Name Service Switch}}
\label{sec:base_nsswitch_conf}

\itindbeg{Name~Service~Switch (NSS)}

Una delle funzionalità di base fornite fin dai primi Unix dalla libreria
standard del sistema (nel caso di Linux la \textit{glibc}) è quella che
consente di associare agli identificativi numerici utilizzati dal kernel dei
nomi simbolici di più immediata fruizione. In generale tutto ciò viene
realizzato grazie ad una serie di funzioni che permettono ai programmi di
ottenere queste informazioni, come le corrispondenze fra nomi degli utenti e
\textit{user ID} o fra nomi dei gruppi ed il \textit{group ID}, che come
abbiamo visto in sez.~\ref{sec:cfg_user_db}, venivano mantenute nei file
\texttt{/etc/passwd} e \texttt{/etc/group}.

In generale oltre che per i nomi degli utenti e dei gruppi, il problema di
ottenere delle corrispondenze fra un identificativo numerico ed un valore
simbolico si presenta anche in altri casi, ad esempio con le corrispondenze
fra nomi assegnati alle macchine e gli indirizzi di rete.\footnote{torneremo
  su questo argomento in sez.~\ref{sec:net_resolv} quando tratteremo questo
  tipo di corrispondenze associate ai parametri relativi alla rete.}
Tradizionalmente queste corrispondenze, e le ulteriori informazioni ad esse
collegate, venivano mantenute in opportuni file di configurazione posti sotto
\texttt{/etc}. 

Con l'evolversi delle funzionalità disponibili sui sistemi più moderni si è
progressivamente manifestata la necessità di mantenere questo tipo di
informazioni anche in maniera diversa, come quella di centralizzarle per
interi gruppi di macchine tramite opportuni servizi di rete. Gli esempi più
comuni sono il NIS (\textit{Network Information Service}) ed LDAP
(\textit{Lightweight Directory Access Protocol}) due servizi di rete con cui
si possono centralizzare le informazioni relative agli utenti.

Con l'introduzione di estensioni che consentissero l'uso di queste nuove
funzionalità si presentava però anche il problema di come indicare alle varie
funzioni di libreria dove prendere le informazioni. All'inizio questo veniva
fatto introducendo tutta la casistica possibile nell'implementazione delle
funzioni stesse, con degli ovvi problemi di estensibilità e compatibilità.
Per risolvere il problema allora è stata creata una interfaccia generica, il
\textit{Name Service Switch}, che permette di demandare a delle librerie
esterne, configurabili in maniera indipendente, le modalità con cui queste
informazioni vengono ottenute. Il sistema venne introdotto la prima volta
nella libreria standard di Solaris, la libreria standard GNU ha ripreso in
seguito lo stesso schema.

Il grande vantaggio del \textit{Name Service Switch} è che diventa possibile
definire in maniera modulare ed estendibile sia delle classi di informazioni,
cosicché qualora si debba fornire qualche nuovo servizio si ha
l'infrastruttura già pronta, che il supporto su cui queste informazioni sono
mantenute, che può essere su file, database o servizi di rete; è possibile
inoltre indicare al sistema anche in quale ordine utilizzare le varie fonti,
permettendo anche configurazioni ibride.

Le modalità di funzionamento del \textit{Name Service Switch} vengono gestite
attraverso il suo file di configurazione principale che è
\index{configurazione!\texttt{/etc/nsswitch.conf}}
\texttt{/etc/nsswitch.conf}. Un esempio di questo file, come installato su una
Debian Squeeze, è il seguente:
\begin{FileExample}[label=/etc/nsswitch.conf]
# /etc/nsswitch.conf
#
# Example configuration of GNU Name Service Switch functionality.
# If you have the 'glibc-doc' and 'info' packages installed, try:
# info libc "Name Service Switch" for information about this file.

passwd:         compat
group:          compat
shadow:         compat

hosts:          files dns
networks:       files

protocols:      db files
services:       db files
ethers:         db files
rpc:            db files

netgroup:       nis
\end{FileExample}

Il formato del file è sempre lo stesso, le linee vuote o che iniziano per
``\texttt{\#}'' vengono ignorate, le altre linee indicano una opzione. La
pagina di manuale contiene una lista completa delle opzioni disponibili. La
prima colonna, terminata dal carattere ``\texttt{:}'' indica una classe di
informazioni, di seguito vengono elencate, separate da spazi, le modalità con
cui queste informazioni possono essere ottenute; la ricerca dei dati sulle
varie fonti sarà eseguita nell'ordine in cui queste sono indicate. L'elenco
delle classi di informazioni disponibili è riportato in
tab.~\ref{tab:cfg_NSS_classes}, ulteriori dettagli possono essere ottenuti
consultando la pagina di manuale del file o la sezione \textit{Name Service
  Switch} delle pagine \textit{info} delle \textit{glibc}.

\begin{table}[htb]
  \footnotesize
  \centering
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Classe} & \textbf{Tipo di corrispondenza}\\
    \hline
    \hline
    \texttt{shadow}   & corrispondenze fra username, 
                        \textit{shadow password} ed altre informazioni
                        relative alla gestione delle password (vedi
                        sez.~\ref{sec:cfg_user_db}).\\  
    \texttt{passwd}   & corrispondenze fra username, identificatori di utente
                        e gruppo principale, shell di default, ecc. (vedi
                        sez.~\ref{sec:cfg_user_db}).\\   
    \texttt{group}    & corrispondenze fra nome del gruppo e proprietà dello 
                        stesso (vedi sez.~\ref{sec:cfg_user_db}).\\  
    \texttt{aliases}  & alias per la posta elettronica.\\
    \texttt{ethers}   & corrispondenze fra indirizzo IP e \textit{MAC address}
                        della scheda di rete (vedi sez.~\ref{sec:net_arp}).\\ 
    \texttt{hosts}    & corrispondenze fra nome a dominio e indirizzo IP (vedi
                        sez.~\ref{sec:net_hosts}).\\  
    \texttt{netgroup} & corrispondenze gruppo di rete e macchine che lo
                        compongono.\\  
    \texttt{networks} & corrispondenze fra nome di una rete e suo indirizzo
                        IP (vedi sez.~\ref{sec:net_name_files}).\\  
    \texttt{protocols}& corrispondenze fra nome di un protocollo e relativo
                        numero identificativo (vedi
                        sez.~\ref{sec:net_name_files}).\\
    \texttt{rpc}      & corrispondenze fra nome di un servizio RPC e relativo 
                        numero identificativo (vedi
                        sez.~\ref{sec:net_rpc_services}).\\  
    \texttt{services} & corrispondenze fra nome di un servizio e numero di
                        porta (vedi sez.~\ref{sec:net_name_files}). \\ 
    \hline
  \end{tabular}
  \caption{Le diverse classi di corrispondenze definite
    all'interno del \textit{Name Service Switch}.} 
  \label{tab:cfg_NSS_classes}
\end{table}
% TODO aggiungere, quando ci saranno, riferimenti a NIS e alias

Delle varie classi di informazioni riportate in tab.~\ref{tab:cfg_NSS_classes}
le prime tre sono utilizzate per gestire in maniera modulare i dati relativi
ad utenti e gruppi, esattamente come questi sono presenti negli omonimi file
sotto \texttt{/etc} visti in sez.~\ref{sec:cfg_user_db}. Le altre attengono ad
altre proprietà, principalmente legate agli identificativi usati dai
protocolli di rete, che tratteremo più avanti in
sez.~\ref{sec:net_name_resolution}.

Per ciascuna modalità di gestione delle informazioni deve esistere una
opportuna libreria che garantisca l'accesso alle stesse con quella modalità.
Queste librerie si trovano tutte sotto \texttt{/lib/} e devono avere un nome
del tipo \texttt{libnss\_\textsl{NOME}.so.\textsl{X}}, dove
\texttt{\textsl{X}} fa riferimento alla versione delle \textit{glibc} che si
sta usando e vale 1 per le \textit{glibc} 2.0 e 2 per le \textit{glibc} 2.1 e
successive, mentre \texttt{\textsl{NOME}} indica il tipo di supporto per
quell'informazione, così come viene scritto in \texttt{/etc/nsswitch.conf}
(nel caso dei supporti citati nell'esempio sarà \texttt{files}, \texttt{db},
\texttt{compat}, ecc.).

Di norma non c'è niente da cambiare in \texttt{/etc/nsswitch.conf}, a meno che
non si debba aggiungere un ulteriore supporto da cui ottenere le
informazioni. Ad esempio nel caso delle informazioni relative agli utenti si
potrebbe voler utilizzare un sistema di autenticazione centralizzato su un
servizio di rete come LDAP. In quel caso si dovrà installare l'apposito
pacchetto di supporto, ed inserire il relativo nome (nel caso \texttt{ldap})
in posizione opportuna nell'elenco dei supporti su cui sono disponibili le
informazioni.\footnote{per un esempio dettagliato di questa configurazione si
  consulti la sez.~2.1.2 di \cite{IS-LDAP}.}

\itindend{Name~Service~Switch (NSS)}

La configurazione di default del \textit{Name Service Switch}, quella vista
nell'esempio precedente, prevede soltanto l'uso dei file classici trattati in
sez.~\ref{sec:cfg_user_db}, ma questo, pur restando ancora oggi quello più
diffuso, è solo uno dei metodi per mantenere le informazioni riguardo gli
\textit{account} degli utenti.  Pertanto esaminare il contenuto di questi file
non è detto sia sufficiente ad identificare tutti gli utenti di un sistema, in
quanto in generale le informazioni potrebbero essere mantenute anche altrove.

Per questo motivo è disponibile un apposito comando,
\index{comando!\texttt{getent}} \texttt{getent}, che consente di interrogare
in maniera generica il sistema del \textit{Name Service Switch} ed ottenere
una lista completa anche quando le informazioni sono distribuite su più
supporti.  Il comando richiede come argomento il nome della classe di
informazioni gestite dal \textit{Name Service Switch} per la quale si vogliono
ottenere i dati, da indicare con uno dei valori riportati in
tab.~\ref{tab:cfg_NSS_classes}, dopo di che esegue una ricerca su tutti i
supporti attivi per tale classe e stampa a video il risultato.

Come si può notare da tab.~\ref{tab:cfg_NSS_classes} le classi relative alle
informazioni degli utenti e dei gruppi gestite dal \textit{Name Service
  Switch} hanno un nome corrispondente al file in cui sono mantenute dal
sistema delle \textit{shadow password}, ed anche il formato con cui esse
vengono mostrate attraverso l'uso di \texttt{getent} segue la stessa
regola. Pertanto volendo ottenere una lista completa degli utenti si potrà
eseguire il seguente comando, ottenendo un risultato analogo al contenuto di
\texttt{/etc/passwd}:
\begin{Console}
piccardi@hain:~/truedoc/corso$ \textbf{getent passwd}
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
...
piccardi:x:1002:1002:Simone Piccardi,,,:/home/piccardi:/bin/bash
admin:x:1003:1003:Utente Amministrativo,,,:/home/admin:/bin/bash
\end{Console}
%$
dove però, se presenti, compariranno anche i dati mantenuti in tutti gli
eventuali altri supporti utilizzati dal \textit{Name Service Switch}.



\subsection{I \textit{Pluggable Authentication Modules}}
\label{sec:cfg_user_PAM}

\itindbeg{Pluggable~Authentication~Modules (PAM)}

La necessità di una maggiore flessibilità della gestione degli utenti non
riguarda soltanto la possibilità di mantenere su diversi supporti i dati loro
associati, ma anche e soprattutto quella di permettere la gestione di diverse
modalità per gestire l'autenticazione. A questo provvede il sistema chiamato
\textit{Pluggable Authentication Modules}, in breve PAM, introdotto
inizialmente su Solaris e poi portato anche su GNU/Linux.

L'idea è quella di realizzare un meccanismo che ricopra per i programmi di
autenticazione il ruolo che ha il \textit{Name Service Switch} per quelli che
richiedono una corrispondenza fra identificatori numerici e simbolici.  Dato
che in questo caso la richiesta è più sofisticata il sistema sarà più
complesso, ma in sostanza si tratta sempre della definizione di una
interfaccia di programmazione generica per cui tutti i programmi che
necessitano di compiere una qualche forma di autenticazione (come
\texttt{login} o \texttt{passwd}) lo fanno attraverso una libreria che fa da
intermediario rispetto al meccanismo con cui poi le operazioni vengono
effettivamente svolte, così che questo possa essere, in maniera totalmente
trasparente ai programmi scelti, sostituito con un altro.

Nel gestire l'insieme dei metodi per l'autenticazione e l'accesso al sistema,
PAM suddivide il lavoro in quattro tipologie di servizio indipendenti fra
loro, illustrate in tab.~\ref{tab:PAM_service}, dove si sono riportate anche
le quattro parole chiave usate nelle configurazioni per identificarle.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{10cm}|}
    \hline
    \textbf{Servizio} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{account} & fornisce il servizio di verifica della presenza di un
                       \textit{account} e della relativa validità (le password
                       sono scadute, si può accedere al servizio, ecc.).\\
    \texttt{auth}    & fornisce il servizio di verifica dell'identità di un
                       utente, in genere sulla base di un meccanismo di
                       sfida/risposta (come dare la password), ma può essere
                       esteso in maniera generica (permettendo l'uso anche di
                       dispositivi ausiliari come smart-card, apparati
                       biometrici ed altro).\\
    \texttt{password}& fornisce il servizio di aggiornamento dei meccanismi di
                       autenticazione (come cambiare la password), ed è
                       strettamente collegato ad \texttt{auth}.\\
    \texttt{session} & fornisce i servizi di preparazione per le risorse che
                       devono essere messe a disposizione dell'utente (ad
                       esempio il montaggio della home directory) all'inizio
                       di una sessione di lavoro e quelli relativi alla
                       liberazione delle stesse alla fine della sessione.\\
    \hline
  \end{tabular}
  \caption{Le quattro tipologie di servizi forniti da PAM.}
  \label{tab:PAM_service}
\end{table}

La flessibilità di PAM è dovuta al fatto che il sistema è implementato come
una libreria dinamica che permette di caricare una serie di \textsl{moduli},
usualmente mantenuti in \texttt{/lib/security}, che realizzano diverse
funzionalità in una o più delle classi di tab.~\ref{tab:PAM_service}.  Una
delle caratteristiche più interessanti di PAM è che questi moduli possono
essere \textsl{impilati} in modo da combinare le funzionalità di ciascuno
nella fornitura di un determinato servizio. Inoltre il sistema permette di
utilizzare impostazioni diverse per le differenti applicazioni che lo usano.

La configurazione di PAM può essere effettuata in due modi; quello più comune
è l'uso di una serie di file, uno per ciascuna applicazione che usa il
sistema, posti nella directory \index{configurazione!\texttt{/etc/pam.d}}
\texttt{/etc/pam.d/}.  In questo modo infatti è molto più semplice per le
singole applicazioni mantenere un proprio file di configurazione. Ogni
applicazione che necessita dell'uso del sistema sarà controllata da un suo
file il cui nome corrisponde a quello del relativo servizio, in genere questo
coincide con quello dell'applicazione stessa, si avranno cioè file come
\texttt{login}, \texttt{su}, \texttt{passwd}, ecc. Uno di questi nomi,
\texttt{other}, è riservato e serve per indicare le regole di default che
verranno applicate tutte le volte che non viene richiesto un servizio
specifico.

Ciascun file contiene una regola per riga, usata per invocare un determinato
modulo; si può proseguire una regola su più righe terminandole con il
carattere ``\texttt{\bslash}'', ed al solito righe vuote ed inizianti per
``\texttt{\#}'' vengono ignorate. Una regola è sempre composta da almeno tre
campi separati da spazi (o tabulatori), al terzo di questi campi, che indica
il modulo di PAM da utilizzare, possono seguire ulteriori campi che
specificano degli argomenti per il modulo, in numero variabile che dipende dal
modulo stesso. La forma generica di una regola da utilizzare in un file di
\texttt{/etc/pam.d/} pertanto è:
\begin{Example}
type  control  module-path  [arguments ...]
\end{Example}

Il primo campo, denominato \texttt{type}, indica, con una delle parole chiave
di tab.~\ref{tab:PAM_service}, la classe di servizi a cui la regola fa
riferimento. Il secondo campo, \texttt{control}, serve a definire il
comportamento che si dovrà avere in caso di successo o fallimento del compito
assegnato al modulo. Per indicare un valore in questo campo nella gran parte
dei casi si può usare una sintassi semplificata che prevede l'utilizzo di una
delle parole chiave riportate in tab.~\ref{tab:PAM_control}, tramite le quali
si indica l'azione che deriva dal controllo effettuato.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Controllo} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{requisite} & il fallimento del modulo invocato comporta l'immediata
                         terminazione della procedura di valutazione, gli 
                         altri eventuali moduli non verranno invocati.\\ 
    \texttt{required}  & il fallimento del modulo comporta il fallimento della
                         procedura di valutazione, ma gli altri moduli
                         specificati nelle regole seguenti vengono comunque
                         invocati.\\ 
    \texttt{sufficient}& il successo del modulo comporta il successo
                         dell'operazione, fintanto che nessun precedente
                         modulo \texttt{required} è fallito.\\
    \texttt{optional}  & il successo o il fallimento del modulo non ha nessuna
                         influenza sul risultato finale a meno che questo non
                         sia l'unico modulo utilizzato.\\
    \hline
  \end{tabular}
  \caption{I principali valori per il campo di controllo dei risultati usati
    nei file di configurazione di PAM.}
  \label{tab:PAM_control}
\end{table}

Infine il terzo campo indica il file (in genere una libreria condivisa, quindi
un file \texttt{.so}) contenente il codice del modulo. Questo viene
normalmente espresso con un pathname relativo alla directory
\texttt{/lib/security/} dove vengono usualmente installati i moduli, ma si può
comunque usare un file qualunque, specificando un pathname assoluto. Al nome
del modulo può seguire una lista (separata da spazi) degli argomenti da
passare a quest'ultimo, che varia da modulo a modulo a seconda delle
funzionalità da esso fornite, anche se come vedremo esistono alcuni valori
utilizzabili per qualunque modulo.

Una forma alternativa di configurazione, oggi totalmente in disuso, è quella
dell'uso del file \index{configurazione!\texttt{/etc/pam.conf}}
\texttt{/etc/pam.conf} in cui si inseriscono tutte le regole di gestione che
starebbero dentro i file di \texttt{/etc/pam.d} ma se questa è presente
\texttt{/etc/pam.conf} viene comunque ignorato. Il file prevede una linea per
ciascuna regola ed al solito si ignorano le righe vuote e quelle inizianti per
``\texttt{\#}''. La differenza con il precedente formato è che queste prendono
un ulteriore campo iniziale che indica il servizio cui la regola fa
riferimento (quello che in \texttt{/etc/pam.d} sarebbe il nome del file),
pertanto una regola sarà nella forma:
\begin{Example}
service  type  control  module-path  [arguments ...]
\end{Example}
dove \texttt{service} indica il nome dell'applicazione cui si applica la
regola (quello che con \texttt{/etc/pam.d} è il nome del file).

La configurazione di un programma per l'uso PAM prevede che nel corrispondente
file sotto \texttt{/etc/pam.d} si elenchino, per ciascuna delle quattro classi
di servizio illustrate in tab.~\ref{tab:PAM_service}, i moduli che si vuole
siano da esso utilizzati. Come accennato questi possono essere
\textsl{impilati}, vale a dire che si può richiedere per un singolo servizio
l'uso di più moduli in successione in modo da poter eseguire diversi tipi di
richieste o di operazioni di controllo e gestione. Ad esempio si può voler
usare una procedura di autenticazione che prenda in considerazione sia le
credenziali poste nei file di sez.~\ref{sec:cfg_user_db} che quelle poste in
un qualche sistema di centralizzazione delle informazioni come LDAP; in questo
caso si specificheranno due moduli diversi, uno per autenticarsi sui file
classici e l'altro per utilizzare LDAP.

Il sistema prevede che per ciascuna tipologia di servizio si elenchino i
moduli che si vogliono utilizzare. Questi, normalmente, verranno eseguiti uno
dopo l'altro nell'ordine in cui sono elencati. Sia l'ordine di esecuzione che
il risultato finale dipendono però dall'azione di controllo richiesta in
risposta al risultato di ciascun modulo, ad esempio con \texttt{sufficient} e
\texttt{requisite} si interrompe immediatamente la scansione della
\textsl{pila}, mentre azioni come \texttt{optional} e \texttt{required} fanno
proseguire con l'esecuzione dei moduli successivi.

Un altro aspetto dell'esecuzione di ciascun modulo, anche questo dipendente
dall'azione di controllo indicata, riguarda l'effetto del risultato ottenuto
dal modulo stesso sul risultato finale restituito da PAM. Ad esempio il
fallimento ottenuto nell'esecuzione di un modulo per cui si è utilizzato
\texttt{required} o \texttt{requisite} comporta il fallimento dell'intera
procedura, \texttt{optional} è ininfluente meno che questo non sia l'unico
risultato ottenuto, mentre \texttt{sufficient} ne comporta il successo, ma
solo se non c'è stato un precedente fallimento di un \texttt{required}.

Oltre alle azioni di controllo di tab.~\ref{tab:PAM_control} si possono usare
come valori per il campo \texttt{control} altre due parole chiave: la prima è
\texttt{include}, che consente di indicare al posto di un modulo un altro file
da cui includere le impostazioni, in questo modo si possono mettere
configurazioni comuni a più servizi in un solo file. Delle configurazioni
presenti nel file incluso verranno usate solo quelle che si applicano al tipo
di servizio specificato prima di \texttt{include}, questo significa che
occorrerà ripetere la direttiva per ciascuno dei servizi di
tab.~\ref{tab:PAM_service}.\footnote{nel caso di Debian viene fornita una
  sintassi non standard, nella forma di una direttiva \texttt{@include file}
  da mettere su una sola riga, che consente di utilizzare tutte le
  configurazioni messe dentro \texttt{file}, vengono poi creati per le
  configurazioni di default anche quattro file \texttt{common-*}, uno per
  ciascuno dei servizi di tab.~\ref{tab:PAM_service}, che vengono inclusi da
  praticamente tutti i file di \texttt{/etc/pam.d/}.} 

La seconda parola chiave è \texttt{substack}, il cui effetto è analogo a
quello di \texttt{include} con la differenza che le regole incluse dal file
vengono considerate come parte di una pila secondaria. Questo comporta che
quando le azioni di controllo impostate nel file incluso richiedono la
terminazione della scansione questa avviene solo per la parte inclusa con tale
direttiva e non per le altre regole contenute nel file da cui è usato
\texttt{substack}.

Infine benché sia la scansione della pila dei moduli che il relativo risultato
sia gestibile nella maggior parte dei casi con le azioni di controllo espresse
nella forma semplificata di tab.~\ref{tab:PAM_control}, esistono casi in cui
occorre un controllo più dettagliato, ottenibile soltanto attraverso la
sintassi completa che consente di specificare la singola azione da associare a
ciascun possibile valore di ritorno restituito dal modulo invocato. Per usare
questa sintassi al posto delle parole chiave di tab.~\ref{tab:PAM_control} si
deve specificare una lista di assegnazioni nella forma \texttt{valore=azione}
compresa fra parentesi quadre. Con \texttt{valore} si indica il nome simbolico
associato al valore di ritorno, e con \texttt{azione} l'azione di controllo
che si vuole gli sia associata.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Azione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{bad}   & indica che il valore di ritorno ottenuto deve essere
                     considerato come un fallimento della richiesta effettuata
                     al modulo, e se questo è il primo fallimento avuto nella
                     scansione della pila questo sarà usato anche come
                     risultato finale.\\
    \texttt{die}   & equivalente all'uso di \texttt{bad} ma con l'ulteriore
                     effetto di concludere immediatamente la scansione della
                     pila.\\ 
    \texttt{done}  & equivalente all'uso di \texttt{ok}, ma con l'ulteriore
                     effetto di concludere immediatamente la scansione della
                     pila.\\
    \texttt{ignore}& il valore di ritorno ottenuto viene ignorato e non avrà
                     nessun effetto sul risultato finale.\\ 
    \texttt{ok}    & indica che il codice di ritorno deve essere considerato
                     come un successo della richiesta effettuata al modulo;
                     ma questo verrà utilizzato solo come risultato finale
                     solo se non sono presenti fallimenti precedenti.\\ 
    \texttt{reset} & cancella lo stato corrente ottenuto dai risultati dei
                     precedenti moduli della pila, ripartendo da zero dal
                     modulo successivo.\\ 
    \hline
  \end{tabular}
  \caption{Azioni associabili ad un valore di ritorno di un modulo di PAM.}
  \label{tab:PAM_actions}
\end{table}

L'interfaccia di PAM prevede infatti che tutti i moduli possono restituire una
serie ben precisa di valori di ritorno, ciascuno dei quali ha un preciso
significato. Alcuni dei più comuni sono \texttt{success}, dal significato
evidente, \texttt{ignore}, che indica la richiesta di ignorare il modulo
stesso (cui in genere si assegna l'azione omonima),
\texttt{new\_authtok\_reqd}, che indica la richiesta di una ulteriore
credenziale di autenticazione, \texttt{user\_unknown} che indica che l'utente
è inesistente. 

La lista completa dei nomi associati ai possibili valori di ritorno è
riportata nella pagina di manuale della configurazione, accessibile con
\texttt{man pam.conf}, ma la documentazione del loro significato è
praticamente nulla.\footnote{viene fatto riferimento al file
  \texttt{/usr/include/security/\_pam\_types.h} che nei commenti ha qualche
  breve spiegazione.} Inoltre si può utilizzare il nome speciale
\texttt{default} per comprendere tutti i valori non esplicitamente indicati in
risposta ai quali impostare una azione prestabilita.

Come azione associabile a ciascun valore di ritorno si può specificare o un
intero positivo \texttt{n} o una delle parole chiave riportate in
tab.~\ref{tab:PAM_actions}. Nel primo caso si richiede di saltare all'interno
della pila dei moduli per andare ad eseguire quello che segue il modulo
corrente di \texttt{n} posizioni, senza che questi contribuisca al risultato
finale; nel secondo caso l'azione sarà invece quella associata alla parola
chiave secondo quanto illustrato in tab.~\ref{tab:PAM_actions}. L'espressione
dei codici semplificati di tab.~\ref{tab:PAM_control} nei termini di questa
sintassi completa è la seguente:
\begin{basedescript}{\desclabelwidth{2.cm}\desclabelstyle{\nextlinelabel}}
\item[\texttt{required}]  equivale a
\texttt{[success=ok new\_authtok\_reqd=ok ignore=ignore default=bad]}
\item[\texttt{requisite}] equivale a \texttt{[success=ok new\_authtok\_reqd=ok
    ignore=ignore default=die]}
\item[\texttt{sufficient}] equivale a \texttt{[success=done
    new\_authtok\_reqd=done default=ignore]}
\item[\texttt{optional}] equivale a \texttt{[success=ok new\_authtok\_reqd=ok
    default=ignore]}
\end{basedescript}

Una possibile configurazione che non rientra in questo schema semplificato
potrebbe essere la seguente, che si è ripresa da quanto specificato per il
modulo \texttt{pam\_securetty.so} per la configurazione di \texttt{login} su
una Debian Squeeze:
\begin{Example}
[success=ok ignore=ignore user_unknown=ignore default=die]
\end{Example}
che è simile all'uso di \texttt{requisite}, ma che evita il fallimento
immediato in caso di utente non esistente, facendo arrivare ai moduli
successivi allo scopo di evitare che si possa distinguere dalla procedura di
login se un utente esiste o meno.

\itindend{Pluggable~Authentication~Modules (PAM)}

La potenza di PAM sta nella grande varietà di moduli che mette a disposizione
per realizzare i compiti più disparati.  Ciascuno di questi prevede, come
accennato, la possibilità di essere invocato passandogli degli argomenti che
consentono di controllarne il comportamento. Prima di esaminare i moduli più
importanti, ed il relativo funzionamento, è però opportuno citare il fatto che
esistono una serie di argomenti generici, riportati in
tab.~\ref{tab:PAM_common_argument}, che possono essere utilizzati per
qualunque modulo, anche se in realtà hanno effetto soltanto se il modulo
stesso ne prevede l'utilizzo.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Argomento} & \textbf{Significato} \\
    \hline
    \hline
%    \texttt{debug} & .\\ 
    \texttt{use\_first\_pass} & il modulo non deve richiedere una password
                                all'utente ma usare quella già fornita in una
                                precedente invocazione di un altro modulo; se
                                questa non è valida all'utente non saranno
                                fatte ulteriori richieste (l'argomento è
                                valido solo per i servizi \texttt{auth} e
                                \texttt{passwd}).\\  
    \texttt{try\_first\_pass} & il modulo deve usare la password già fornita
                                in una precedente invocazione di un altro
                                modulo, ed eseguire direttamente una richiesta
                                qualora questa non sia valida (l'argomento è
                                valido solo per i servizi \texttt{auth} e
                                \texttt{passwd}).\\ 
%    \texttt{use\_mapped\_pass}& .\\
    \texttt{expose\_account}  & segnala al modulo che può essere più
                                permissivo nel rivelare informazioni riguardo
                                l'utente (in genere questo viene evitato per
                                non fornire appigli ad un attaccante).\\ 
    \texttt{use\_authtok}     & forza il modulo a non richiedere una nuova
                                password (quando si esegue una cambiamento
                                della stessa) ma ad usare quella proveniente
                                da un modulo precedente (l'argomento è
                                valido solo per il servizio \texttt{passwd}).\\
    \hline
  \end{tabular}
  \caption{Alcuni argomenti generici che possono essere passati ai moduli di
    PAM.}  
  \label{tab:PAM_common_argument}
\end{table}

In particolare sono molto utili argomenti come \texttt{use\_first\_pass} e
\texttt{try\_first\_pass} che consentono, quando si utilizzano più moduli che
devono eseguire una operazione richiedendo una password, di non ripetere la
richiesta della stessa ad ogni invocazione, facendo invece riferimento a
quanto immesso nella invocazione di un modulo precedente.

Il primo dei moduli che prendiamo in considerazione è
\texttt{pam\_unix},\footnote{in questa trattazione indicheremo i moduli per
  nome, tralasciando il \texttt{.so} finale, che però deve essere usato quando
  li si richiamano nelle configurazioni di \texttt{/etc/pam.d/}.} che è senza
dubbio uno dei più importanti in quanto è quello che fornisce autenticazione e
gestione delle risorse degli utenti secondo le modalità classiche di Unix ed è
il default usato dalla gran parte delle distribuzioni. Il modulo utilizza i
file di sez.~\ref{sec:cfg_user_db} per quanto riguarda sia la verifica che il
cambiamento della password, sia per i controlli ausiliari relativi alla
validità dell'utenza e delle credenziali e delle relative scadenze. Si
incarica inoltre di registrare gli accessi nei log di sistema, per questo
motivo deve essere utilizzato per tutti e quattro i servizi \texttt{auth},
\texttt{password}, \texttt{account} e \texttt{session}.

L'uso di questo modulo implementa in sostanza il funzionamento classico di un
sistema Unix così come era prima dell'uso di PAM, anche se sono presenti
alcune piccole differenze e migliorie. Una differenza è che agli utenti senza
password (quelli a cui si è tolta la ``\texttt{x}'' dal secondo campo di
\texttt{/etc/passwd}) viene comunque negato l'accesso, a meno di non aver
passato l'opzione \texttt{nullok} come argomento. Un comportamento più vicino
a quello classico, usato da molte distribuzioni, può essere ottenuto con
\texttt{nullok\_secure}, in cui si continua a garantire l'accesso senza
password ma solo se questo avviene su uno dei terminali consentiti elencati in
\texttt{/etc/securetty} (vedi sez.~\ref{sec:cfg_login}). Queste due opzioni
hanno effetto solo se usate sul servizio \texttt{auth}.

Alcune estensioni vengono attivate con l'uso di altri argomenti, ad esempio si
può richiedere la cifratura della password con algoritmi diversi usando le
opzioni \texttt{md5}, \texttt{sha256}, \texttt{sha512},\footnote{la
  configurazione di default prevede l'uso di \texttt{md5} per l'algoritmo MD5,
  gli altri sono algoritmi alternativi, e più sicuri, che possono essere
  utilizzati qualora siano supportati.} imporre una dimensione minima della
stessa con l'argomento \texttt{min=n} dove \texttt{n} indica il numero di
caratteri, o impedire il riuso delle ultime \texttt{n} password utilizzate con
\texttt{remember=n}. Le vecchie password saranno mantenute in
\texttt{/etc/security/opasswd}, così da evitarne il riutilizzo. Queste
opzioni, attenendo al cambiamento della password, hanno effetto solo se
indicate sul servizio \texttt{password}.

Oltre a \texttt{pam\_unix} per reimplementare il comportamento classico di un
sistema Unix sono disponibili una serie di altri moduli elementari che
consentono di utilizzare attraverso PAM i vari file di configurazione della
procedura di login illustrati in sez.~\ref{sec:cfg_login}. Ad esempio usare
\texttt{pam\_motd} sul servizio \texttt{session} consente di stampare il
contenuto di \texttt{/etc/motd} all'inizio di una sessione, mentre sul
servizio \texttt{auth} si possono usare \texttt{pam\_nologin} per disabilitare
l'accesso agli utenti normali se è presente \texttt{/etc/nologin} e
\texttt{pam\_securetty} per impedire l'accesso all'amministratore dai
terminali non elencati in \texttt{/etc/securetty}.

Un altro modulo che consente di ottenere in maniera generica con PAM una delle
funzionalità fornite una volta direttamente da \texttt{login} è
\texttt{pam\_limits}, che consente di imporre dei limiti su alcune delle
risorse del sistema che un utente può utilizzare durante una sessione, come un
numero massimo di processi contemporanei, numero di file aperti, quantità di
memoria utilizzata, il tempo massimo di CPU, ed altre risorse più
complesse. Le versioni di \texttt{login} precedenti all'uso di PAM,
effettuavano direttamente l'impostazione dei limiti con il file
\texttt{/etc/limits}, oggi non più utilizzato.

Il kernel infatti supporta la possibilità per qualunque processo di impostare
una serie di limiti su alcune delle risorse che da esso verranno
utilizzate. Questi limiti possono essere impostati solo all'interno del
singolo processo,\footnote{per i dettagli sul funzionamento si può consultare
  sez.~8.3.2 di \cite{GaPiL}.} ma vengono ereditati nella creazione di
eventuali processi figli ed in questo modo una volta impostati su un processo
iniziale (ad esempio la shell di login) possono essere mantenuti per tutti i
comandi da essa eseguiti. 

La shell consente di controllare i limiti sulle risorse con il comando interno
\index{comando!built-in!\texttt{ulimit}} \texttt{ulimit}, che oltre a mostrare
la situazione corrente (con l'opzione \texttt{-a} che stampa i valori correnti
dei limiti) permette anche di impostarne i valori. Questi, come avviene per le
quote disco che tratteremo in sez.~\ref{sec:disk_quota}, prevedono la
possibilità di avere due valori, un limite ``\textsl{soffice}'' (o
\textit{soft limit}, selezionabile con l'opzione \texttt{-S}) o un limite
``\textsl{duro}'' (\textit{hard limit}, selezionabile con l'opzione
\texttt{-H}). Per le altre opzioni, che permettono di indicare il limite ed il
relativo valore, si consulti la pagina di manuale della shell.

È cura del kernel assicurarsi che un processo non possa utilizzare una risorsa
per valori superiori a quelli indicati nel rispettivo limite
``\textsl{soffice}'', generando un errore quando questi vengono raggiunti. Il
valore del limite ``\textsl{duro}'' serve invece come tetto massimo che può
essere assegnato ad un limite ``\textsl{soffice}''. Un utente ordinario può
imporsi dei limiti assegnando un valore sia al limite ``\textsl{soffice}'' che
a quello ``\textsl{duro}'', il primo però non potrà mai superare quello del
secondo. Inoltre una volta che un utente abbia impostato un limite
``\textsl{duro}'' il valore di quest'ultimo potrà solo essere ulteriormente
ridotto, sempre che non si sia l'amministratore che può alzare i valori anche
di quest'ultimo.

L'uso dei limiti consente di contrastare efficacemente i comportamenti
inappropriati di quegli utenti che cercano di abusare delle risorse del
sistema dando origine ad eventuali disservizi, o ad evitare tentativi
espliciti di esaurimento delle risorse come le \textit{fork bomb}, in cui si
lanciano un numero indefinito di processi fino a bloccare completamente il
sistema.  Il problema è che i limiti devono essere imposti dall'amministratore
solo a monte della procedura di collegamento al sistema; nel caso di un login
da console questo potrebbe essere fatto usando il comando \texttt{ulimit} nel
file \texttt{/etc/profile}, ma varrebbe solo per le shell che usano questo
file, ed inoltre il limite verrebbe applicato in maniera indifferenziata.

La soluzione a questo problema viene fornita appunto dal modulo
\texttt{pam\_limits}, da inserire come \texttt{requisite} nelle regole
associate al servizio \texttt{session} per i vari programmi che danno accesso
al sistema. Il modulo si appoggia al file
\index{configurazione!\texttt{/etc/security/limits.conf}}
\texttt{/etc/security/limits.conf} all'interno del quale si possono impostare
tutti i limiti che verranno attivati fin dall'inizio della sessione di lavoro,
e mantenuti pertanto nel corso della stessa. Il file prevede una sintassi
molto semplice dove al solito righe vuote o inizianti con ``\texttt{\#}''
vengono ignorate; ciascuna riga è divisa in quattro campi separati da spazi,
nella forma:
\begin{Example}
domain        type  item  value
\end{Example}

Il primo campo, \texttt{domain}, indica a chi si applica la regola, vi si può
specificare un nome utente, o un nome di gruppo (apponendovi il carattere
``\texttt{@}''), o l'indicazione di un valore di default usando il carattere
``\texttt{*}''. Il secondo campo, \texttt{type}, specifica il tipo di limite e
può essere \texttt{soft} o \texttt{hard} per indicare i rispettivi tipi, o
``\texttt{-}'' per indicare un limite sia \textit{soft} che \textit{hard}. Il
terzo campo, \texttt{item}, indica a quale risorsa si vuole applicare il
limite, il cui valore deve essere indicato nell'ultimo campo. Ciascuna risorsa
viene identificata da una parola chiave, ed uno specifico intervallo ed unità
di misura per il valore del limite; si sono riportate le più rilevanti in
tab.~\ref{tab:pam_limits_item}, per l'elenco completo si consulti la pagina di
manuale, accessibile con \texttt{man limits.conf}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Nome} & \textbf{Risorsa} \\
    \hline
    \hline
%    \texttt{core} & .\\ 
%    \texttt{data} & .\\ 
    \texttt{fsize}   & massima dimensione utilizzabile per un singolo file.\\ 
%    \texttt{memlock} & .\\ 
    \texttt{nofile}  & massimo numero di file che un processo può aprire in
                       contemporanea.\\  
%    \texttt{rss} & .\\ 
%    \texttt{stack} & .\\ 
    \texttt{cpu}     & massimo tempo di CPU utilizzabile dal singolo
                       processo.\\  
    \texttt{nproc}   & numero massimo di processi che possono essere creati
                       dallo stesso utente.\\ 
%    \texttt{as} & .\\ 
    \texttt{maxlogins}&numero massimo di collegamenti contemporanei al
                       sistema da parte dell'utente (valido solo per utenti
                       normali).\\
    \texttt{maxsyslogins}& numero massimo di collegamenti contemporanei al
                       sistema (come somma di quelli tutti gli utenti) oltre
                       il quale l'utente non avrà accesso.\\ 
%    \texttt{priority}    & .\\ 
%    \texttt{locks} & .\\ 
%    \texttt{msgqueue} & .\\ 
    \texttt{nice}    & massimo valore di \textit{nice} che può essere
                       assegnato ad un processo.\\ 
%    \texttt{rtprio} & .\\ 
    \hline
  \end{tabular}
  \caption{Nomi delle principali risorse che possono essere specificate come
    valore per il terzo campo di \texttt{/etc/security/limits.conf}.}  
  \label{tab:pam_limits_item}
\end{table}

Si noti poi come oltre alle limitazioni sull'uso delle risorse da parte dei
singoli processi, \texttt{pam\_limits} consenta anche di impostare limiti
relativi alla situazione generale del sistema, come quelli sul numero massimo
di collegamenti contemporanei. Un esempio del contenuto di questo file
potrebbe essere il seguente:
\begin{FileExample}[label=/etc/security/limits.conf]
*               hard    nproc          1024
*               hard    nofile         1024
@student        hard    nproc          100
@student        hard    nofile         100
@student        -       maxlogin       10
\end{FileExample}

Un primo esempio di come le funzionalità dei metodi tradizionali possono
essere estese attraverso l'uso di PAM è quello del modulo
\texttt{pam\_cracklib}, da utilizzare nel servizio \texttt{password}. Il
modulo consente di impostare delle politiche di gestione sul tipo di password
usate dagli utenti, supportando una analisi di quelle da essi fornite nei
confronti di un dizionario per evitare l'uso di parole comuni facili da
indovinare. Consente così all'amministratore di imporre criteri che
garantiscano una sufficiente complessità delle stesse per rendere più
difficoltoso anche un attacco a dizionario.

L'uso del modulo fa sì che alla prima immissione di una password questa venga
controllata per verificarne una sufficiente complessità sia facendo ricorso ad
un dizionario che ad eventuali regole aggiuntive. Se il controllo viene
passato allora verrà effettuata la seconda richiesta per conferma, altrimenti
la password sarà rifiutata e all'utente sarà richiesto di immetterne una
diversa con un breve messaggio esplicativo.  Il modulo usa le librerie
\textit{cracklib}, da cui deriva il nome, per effettuare il controllo della
password nei confronti di uno o più dizionari di parole comuni ed applica poi
una serie di ulteriori controlli, come il fatto che la nuova password non sia
troppo simile alla precedente, o troppo corta o già usata in precedenza come
per \texttt{pam\_unix}.

Il modulo prevede una serie di argomenti che consentono di controllare le
condizioni aggiuntive. Con \texttt{minlen}, assegnato ad un intero positivo,
si indica la lunghezza minima di una password; il default è 9, ma al numero di
caratteri effettivo viene aggiunto anche un bonus di un punto per ciascun tipo
di carattere diverso che si è messo nella password (numero, maiuscola,
minuscola o punteggiatura) per cui si può superare il limite anche con un
numero inferiore di caratteri. Un altro argomento che consente di agire sulla
complessità richiesta è \texttt{difok} (anch'esso da assegnare ad un intero
positivo) che richiede il numero minimo di caratteri che devono essere diversi
dalla password precedente. Un esempio di uso di questo modulo è il seguente:
\begin{Example}
password  required pam_cracklib.so difok=3 minlen=10 
\end{Example}

Un secondo esempio di estensione delle funzionalità di controllo che tramite
PAM possono essere applicate a qualunque programma, è quello del modulo
\texttt{pam\_listfile}. Questo modulo infatti consente di attivare un
meccanismo di restrizione dell'accesso basato sul contenuto di un file in cui
si elenca la lista dei valori consentiti o proibiti di una certa proprietà
associata alla sessione (username, terminale, macchina da cui ci si collega,
ecc.). In questo modo diventa possibile applicare restrizioni aggiuntive,
indipendenti fra loro, al singolo programma che usa il modulo.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|l|}
    \hline
    \textbf{Valore} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{tty}   & terminale di accesso.\\ 
    \texttt{user}  & nome dell'utente.\\ 
    \texttt{rhost} & macchina remota.\\ 
    \texttt{ruser} & utente remoto.\\ 
    \texttt{group} & gruppo dell'utente.\\ 
    \texttt{shell} & shell di login.\\ 
    \hline
  \end{tabular}
  \caption{Valori usabili per l'argomento
    \texttt{item} del modulo \texttt{pam\_listfile}.}  
  \label{tab:pam_listfile_item}
\end{table}

La proprietà della sessione che si vuole controllare nei confronti della
propria lista si imposta con l'argomento \texttt{item}, da assegnare ad uno
dei valori di tab.~\ref{tab:pam_listfile_item}.  Gli altri argomenti necessari
al funzionamento del modulo sono \texttt{sense} cui assegnare rispettivamente
i valori \texttt{allow} o \texttt{deny} a seconda che si voglia usare la lista
per consentire o negare l'accesso e \texttt{file}, cui assegnare il pathname
che identifica il file in cui mette l'elenco dei valori della proprietà
indicata con \texttt{item}. La documentazione più dettagliata sul modulo ed i
suoi argomenti può essere ottenuta dalla relativa pagina di manuale,
accessibile con \texttt{man pam\_listfile}.


\section{Amministrazione sistemistica di una base di dati}
\label{sec:database_admin}

Benché la gestione delle basi di dati sia una attività usualmente distinta
dalla gestione sistemistica,\footnote{in genere a questo è dedicata la figura
  del DBA (\textit{Data Base Administrator}) che richiede competenze
  specifiche sulle migliori modalità di gestione dei dati e della loro
  ottimizzazione, tutti argomenti che non prenderemo assolutamente in esame.}
la diffusione dell'uso dei database relazionali comporta anche per
l'amministratore di sistema la necessità di avere un minimo di nozioni al
riguardo. Pertanto in questa sezione tratteremo le problematiche di gestione
di un database esclusivamente dal punto di vista di un amministratore di
sistema, in particolare per quanto riguarda la gestione sistemistica di server
come PostgreSQL o MySQL, ed introdurremo alcune nozioni elementari sul
linguaggio SQL.

\subsection{Alcuni concetti base dei database relazionali}
\label{sec:sb_relational_database}

Benché la teoria dei database relazionali vada al di là di quanto interessa
trattare in questo testo, vale la pena illustrare alcune nozioni di base che
consentano quantomeno di avere una idea del quadro generale in cui si va ad
operare quando si ha a che fare con queste problematiche, ed introdurre un
minimo di terminologia che consenta di orientarsi nella documentazione.

Si tenga comunque presente che il concetto di base di dati è molto più
generale di quello di database relazionale, tanto che oggi si sta assistendo
ad un fiorire di database, detti \textit{NoSQL}, che non adottano più questo
modello, che è sostanzialmente basato sulla strutturazione dei dati in forma
di tabelle. 

Per molti anni il vantaggio di avere un modello con una chiara
rappresentazione matematica ed implementazioni ben funzionanti ha portato a
cercare di ridurre tutti i problemi a questo modello, anche se esistono da
molto tempo modelli alternativi, come quello ad albero usato da LDAP e quello
chiave-valore usato da BerkleyDB. Oggi ci si sta rendendo conto delle sue
inadeguatezze e si stanno sviluppando modelli alternativi, che sono più vicini
al tipo di dati che si devono gestire ma la trattazione di questi argomenti va
comunque al di là dello scopo di questo testo.

Semplificando molto una teoria piuttosto complessa, che non tratteremo neanche
superficialmente, si può considerare un database relazionale come un insieme
di tabelle di dati.  Ogni tabella è costituita da un elenco di dati
organizzati in righe (che vengono chiamate anche \textit{record} o
\textit{tuple}), dove ciascuna riga individua un singolo oggetto nella
tabella. Ciascuna riga è composta da una serie di campi detti \textsl{campi} o
\textsl{attributi} (in inglese \textit{field} o \textit{attributes}), che
vanno a costituire le colonne della tabella. Avendo in genere detti campi un
significato preciso, vengono identificati da un nome, che viene a costituire
la struttura della tabella stessa, definita appunto come l'elenco dei campi
che ne costituiscono le righe.

In sostanza creare una tabella significa definire l'elenco dei campi che
compongono le righe in essa contenute, associando a ciascuno di essi un nome
identificativo ed il tipo di valore che può assumere, esistono ovviamente
diversi tipi di valori possibili, ed anche il tipo di valore va a costituire
la struttura di una tabella.  Una riga sarà costituita dalla serie dei valori
avuti da ciascuno dei suoi campi, alcuni dei quali possono anche essere
assenti o indefiniti, nel qual caso si parla di valore ``\textsl{nullo}'' (il
cosiddetto \textit{null value}), che viene identificato specificamente nel
linguaggio SQL, che vedremo in sez.~\ref{sec:sb_sql_lang}, da una opportuna
parola chiave (\texttt{NULL}).  Il contenuto di una tabella è semplicemente
costituito dall'insieme dei \textit{record} che essa contiene, che non è
previsto debba avere alcun ordinamento specifico.

Uno dei concetti principali nei database relazionali infatti è quello dell'uso
delle cosiddette \textsl{chiavi} per effettuare le ricerche.  Il concetto è di
natura logica, si tratta in sostanza di usare i valori che hanno alcuni campi
(sia presi singolarmente che eventualmente come insieme) per ottenere i
\textit{record} che hanno quel valore. In pratica le \textit{chiavi} non sono
altro che i campi sui quali si effettuano le ricerche, sui quali viene
eseguita una opportuna indicizzazione in modo da renderle il più veloci
possibile.

Quando una chiave consente di identificare in maniera univoca una riga della
tabella, si parla di \textsl{chiave primaria} (o \textit{primary key}) della
tabella. Spesso queste \textit{primary key} vengono generate automaticamente
per essere sicuri dell'univocità, dato che alcuni campi non è detto abbiano
questa proprietà.  Questa caratteristica ne comporta delle altre, ad esempio
una \textit{primary key} non può avere valore nullo, non può essere
modificata, e non può essere riutilizzata in caso di cancellazione della riga
corrispondente.

Il nome di database relazionale dato a questo tipo di strutturazione dei dati
deriva dal fatto che una tabella può essere vista come una
``\textsl{relazione}''\footnote{il concetto deriva direttamente dall'algebra
  ed ha una fondazione matematica rigorosa, per approfondimenti si consulti ad
  esempio \url{http://it.wikipedia.org/wiki/Algebra_relazionale}.} fra i dati
che la costituiscono, tanto che talvolta questo (o l'inglese
\textit{relation}) è un nome alternativo con cui vengono indicate le tabelle.
La potenza di un database relazionale sta nel fatto che grazie alle chiavi
primarie si possono definire delle relazioni fra tabelle diverse (in realtà
l'argomento sarebbe molto più ampio, ma la sua trattazione va al di là di
quanto appropriato per questa introduzione.)

Si può cioè avere una tabella di autori con i dati relativi agli stessi, ad
esempio nome e cognome ed età, ed una di libri con rispettivi dati, ad esempio
titolo ed editore ed anno di pubblicazione, e metterle in \textsl{relazione}
fra loro usando ad esempio come campo autore nella tabella dei libri il valore
di una chiave primaria della tabella degli autori, in modo che questi possano
essere identificati univocamente anche se i loro dati sono mantenuti in
maniera indipendente su una diversa tabella. In questo caso il valore del
campo autore nella tabella dei libri è quello che si chiama una \textsl{chiave
  esterna} o \textit{foreign key}.

In genere si indica con RDBMS (\textit{Relational Database Management System})
il software che consente di operare su dati mantenuti in un database
relazionale, anche se spesso si finisce semplicemente per chiamarlo
\textit{database}. Un RDBMS serve ad operare in maniera veloce ed efficiente
sui dati attraverso il linguaggio SQL (che vedremo più avanti in
sez.~\ref{sec:sb_sql_lang}), esso deve pertanto gestire da una parte
l'interpretazione del linguaggio e la esecuzione dei relativi comandi,
dall'altro l'opportuno salvataggio dei dati e la loro integrità.

In genere un software RDBMS consente di gestire più basi di dati, vale a dire
tanti database distinti, con dati diversi, ed oltre a consentire la
manipolazione degli stessi con il linguaggio SQL fornisce in genere anche il
supporto per poter avere gli opportuni controlli di accesso e la possibilità
di creare utenti e assegnare loro diverse capacità relative all'uso dei dati
stessi.


\subsection{Configurazione e gestione di base di PostgreSQL}
\label{sec:sb_postgres}

PostgreSQL è uno dei più completi, stabili ed efficienti RDBMS disponibili,
che supporta numerose funzionalità avanzate come transazioni, subselect,
trigger, viste, \textit{foreign key} ed integrità referenziale che gli
consentono di poter sostituire il ben più famoso (e costoso) Oracle, con il
quale è in grado di lottare ad armi pari nella gran parte dei casi.

Non tratteremo l'installazione del programma, in quanto questo viene fornito
già pacchettizzato dalle principali distribuzioni,\footnote{nel caso di Debian
  sono addirittura pacchettizzate le diverse versioni stabili, e per Lenny
  sono disponibili sia la versione 7.4 che la 8.3.} e trattandosi di un server
di grande importanza per la propria infrastruttura è sempre opportuno
utilizzare una versione pacchettizzata per la quale la propria distribuzione
garantisca il supporto per gli aggiornamenti. Anche PostgreSQL, come per la
gran parte degli RDBMS, adotta un modello client/server, in cui l'accesso ai
dati viene fornito da un programma server (nel caso
\index{demone!\texttt{postmaster}} \texttt{postmaster}) cui si possono fare
richieste tramite opportuni client, pertanto a seconda dei casi si dovranno
installare i relativi pacchetti.

La configurazione (del server) viene mantenuta all'interno di una directory
dipendente dall'installazione. Quando il programma viene installato dai
sorgenti l'approccio degli sviluppatori è quello di mantenere tutti i file,
dati e configurazioni, nella directory di installazione; questo però contrasta
con le direttive del \textit{Filesystem Hierarchy Standard}, per cui le
versioni pacchettizzate possono fare scelte diverse. Ad esempio nel caso di
Debian i file di configurazione vengono riportati in una directory sotto
\texttt{/etc/} nella forma \texttt{/etc/postgresql/\textsl{N.N}/main} (dove
\texttt{\textsl{N.N}} è il numero della versione, ad esempio 7.4 o
8.3).\footnote{la scelta della sottodirectory con la versione è dovuta al
  supporto contemporaneo di diverse versioni del programma.} Il file di
configurazione principale è \index{configurazione!\texttt{postgresql.conf}}
\texttt{postgresql.conf} che contiene le direttive di configurazione nella
classica forma \texttt{chiave=valore}, con la solita convenzione di ignorare
righe vuote e tutto ciò che segue il carattere ``\texttt{\#}''.

Non staremo qui a trattare i dettagli della configurazione del server che,
riguardando principalmente le modalità di gestione ed utilizzo dei dati e le
relative ottimizzazioni, vanno al di là dello scopo introduttivo di questo
paragrafo, se però si vuole che il server possa essere raggiunto via rete e
non soltanto in locale occorrerà inserire la direttiva:\footnote{il default è
  ascoltare soltanto sull'indirizzo locale (per i concetti relativi alle reti
  si rimanda al solito a sez.~\ref{sec:net_tcp_ip}).}
\begin{Example}
listen_addresses = '*'
\end{Example}

Il secondo file di interesse per la configurazione di base di PostgreSQL è
\index{configurazione!\texttt{pg\_hba.conf}} \texttt{pg\_hba.conf}, che
definisce le regole per il controllo di accesso e l'autenticazione da parte
dei client. Il file è composto da una serie di righe ciascuna delle quali
indica una modalità di accesso ed autenticazione, e la prima che corrisponde
alle modalità di accesso che si stanno usando verrà utilizzata per
l'autenticazione.

Le righe sono composte di un serie di campi separati da spazi vuoti, il primo
campo indica la modalità di connessione al server, ed in genere si usa o il
valore \texttt{local} per usare un socket locale, o il valore \texttt{host}
per una connessione via rete. I due campi successivi sono identici
indipendentemente dal valore del primo campo: il secondo indica il nome del
database a cui si applica il criterio di accesso, ed il valore più comune è
\texttt{all} per indicarli tutti; il terzo indica l'utente, e di nuovo il
valore \texttt{all} indica l'utente generico.

Nel caso si sia usato come criterio di accesso \texttt{host}, i campi
successivi servono per determinare gli indirizzi di rete consentiti, si può
specificare il singolo indirizzo e rete in notazione CIDR, o in due campi
separati indirizzo e maschera di rete (al solito per queste notazioni si fa
riferimento ai concetti spiegati in sez.~\ref{sec:net_tcp_ip}).  Si faccia
attenzione, nel caso di singolo indirizzo IP, a specificarlo comunque come
rete in una delle due forme.

Nel caso si sia usato come criterio di accesso \texttt{local}, non è
necessario specificare nessun indirizzo e può passare direttamente agli ultimi
due campi che indicano il metodo di autenticazione e le eventuali relative
opzioni. In genere per le connessioni via rete si usa il metodo \texttt{md5}
che indica che l'utente deve essere autenticato con il valore della password
cifrata mantenuto dal server stesso. Nel caso di \texttt{local} si può far
ricorso al metodo \texttt{password}, che richiede l'invio di una password in
chiaro, o \texttt{ident sameuser} che richiede che il client sia posto in
esecuzione da un utente unix con lo stesso nome usato dal rispettivo utente
del database.\footnote{questa è la modalità usata da Debian per dare accesso
  all'utente \texttt{postgres} usato per la gestione generale del database,
  creando un utente omonimo nel sistema, a cui viene anche assegnata la
  proprietà dei file del server.}

Un estratto di questo file, preso dalla versione installata di default da una
Debian Lenny, è il seguente, sarà necessaria una modifica soltanto nei casi in
cui si vogliano consentire accessi da altre reti, aggiungendovi una opportuna
riga \texttt{host}:
\begin{FileExample}[label=pg\_hba.conf]
# Database administrative login by UNIX sockets
local   all         postgres                          ident sameuser

# TYPE  DATABASE    USER        CIDR-ADDRESS          METHOD

# "local" is for Unix domain socket connections only
local   all         all                               password
# IPv4 local connections:
host    all         all         127.0.0.1/32          md5
# IPv6 local connections:
host    all         all         ::1/128               md5
\end{FileExample}

Il comando principale per operare su un database PostgreSQL è
\index{comando!\texttt{psql}} \texttt{psql}, che invoca il programma client
con cui ci si può connettere al server per le eseguire operazioni a riga di
comando. Se usato interattivamente le istruzioni da eseguire verranno lette da
un prompt sul terminale, ma lo si può usare anche in modalità non interattiva
facendo leggere le istruzioni da un file o comunque con una redirezione dello
\textit{standard input}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-f \textsl{file}} & legge i comandi da eseguire file passato come
                                parametro.\\
    \texttt{-c \textsl{cmd}}  & esegue il comando passato come parametro (da
                                inserire come stringa) ed esce
                                immediatamente.\\
    \texttt{-o \textsl{file}} & scrive i risultati sul file passato come
                                parametro.\\ 
    \texttt{-l}               & elenca i database disponibili sul server.\\ 
    \hline
    \texttt{-h \textsl{host}} & si collega all'indirizzo di rete passato come
                                parametro.\\ 
    \texttt{-p \textsl{port}} & si collega alla porta passata come parametro.\\
    \texttt{-U \textsl{user}} & si collega con l'utente passato come
                                parametro.\\  
    \texttt{-W}               & forza la richiesta della password utente prima
                                di collegarsi.\\  
    \hline
  \end{tabular}
  \caption{Principali opzioni del comando \texttt{psql}.}  
  \label{tab:psql_options}
\end{table}

Il comando richiede come argomenti il nome del database su cui si vuole
operare e di seguito il nome dell'utente che si vuole utilizzare. Se non si
specifica un database si potranno usare solo i comandi di servizio che non
fanno riferimento ai dati, e se non si specifica un nome utente verrà usato
l'\textit{username} di chi esegue il comando. Il default è usare una
connessione locale, ma ci si può collegare via rete indicando esplicitamente
usando l'opzione \texttt{-h} per indicare la macchina a cui collegarsi (per
indirizzo IP o nome a dominio). Le opzioni principali sono riassunte in
tab.~\ref{tab:psql_options}, per la descrizione completa al solito si faccia
riferimento alla pagina di manuale.

Una volta effettuata la connessione al server, ed a meno che non si sia
indicato un file da cui leggere i comandi con l'opzione \texttt{-f} o con la
redirezione dello \textit{standard input}, il comando mette a disposizione un
prompt su cui scrivere interattivamente le proprie istruzioni dopo aver
stampato un messaggio di benvenuto con una legenda dei \textsl{comandi di
  controllo} più importanti. Si tratta di comandi che attengono alla gestione
del server stesso, e non alle operazioni sui dati per i quali si deve usare il
linguaggio illustrato in sez.~\ref{sec:sb_sql_lang} e si distinguono dalle
istruzioni previste dal linguaggio SQL in quanto sono preceduti dal carattere
``\texttt{\bslash}''.\footnote{in realtà alcuni di essi sono solo
  abbreviazioni predefinite dei comandi SQL necessari ad ottenere le
  informazioni volute.} Un elenco degli stessi può essere ottenuto con
``\texttt{\bslash ?}'', mentre con ``\texttt{\bslash h}'' si ottengono invece
i comandi SQL. Per uscire dalla riga di comando si può usare ``\texttt{\bslash
  q}''. Gli altri comandi di controllo più importanti sono riportati in
tab.~\ref{tab:psql_control_command}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|c|p{8cm}|}
    \hline
    \textbf{Comando} & \textbf{Significato} \\
    \hline
    \hline
    \verb|\c| & si connette a un database (da passare come parametro).\\
    \verb|\q| & esce dal programma.\\
    \verb|\l| & stampa l'elenco dei database presenti.\\
    \verb|\!| & esegue il comando di shell passato come parametro.\\
    \verb|\d| & stampa l'elenco delle tabelle del database corrente.\\
    \verb|\u| & stampa l'elenco degli utenti.\\
    \hline
  \end{tabular}
  \caption{Principali comandi di controllo di \texttt{psql}.}  
  \label{tab:psql_control_command}
\end{table}

Come accennato PostgreSQL fornisce anche un sistema di controllo degli accessi
basato sulla presenza di utenti a cui possono essere assegnati diversi
permessi sia sulle possibilità di intervenire sui singoli database gestiti dal
server, sia in termini di amministrazione generale del server stesso. Gli
utenti vengono mantenuti su delle tabelle interne al database, ma per
semplificarne la gestione sono stati creati due comandi appositi. In realtà
entrambi i comandi non sono che \textit{wrapper} per i comandi SQL
\texttt{CREATE ROLE} e \texttt{DROP ROLE} (nel gergo di PostgreSQL gli utenti
sono chiamati \textsl{ruoli}), e possono essere usati anche in questo modo
dall'interno del client.

Il primo è \index{comando!\texttt{createuser}} \texttt{createuser} e si
utilizza per creare un nuovo utente, il comando richiede semplicemente come
argomento un nome utente, che verrà creato. In realtà, dato che il comando non
è altro che un \textit{wrapper} per l'esecuzione di comandi SQL, la creazione
può avvenire soltanto se l'utente di sistema che si usa per eseguire questo
comando è in grado di collegarsi al database e l'utente PostgreSQL a cui
corrisponde ha sufficienti privilegi (che sono quelli di amministratore o la
capacità di creare altri \textsl{ruoli}).

Il comando prevede che si possa specificare se il nuovo utente sarà un
amministratore (\textit{superuser}) con l'opzione \texttt{-s}, se può creare
nuovi database con l'opzione \texttt{-d}, se può creare nuovi utenti con
l'opzione \texttt{-r}, ma se non si specifica nulla queste indicazioni
verranno chieste interattivamente.  Si può inoltre richiedere l'impostazione
di una password per il nuovo utente, che verrà richiesta interattivamente, con
l'opzione \texttt{-P}. Infine il comando consente di eseguire le operazioni
collegandosi ad un database remoto con \texttt{-h}, e supporta le stesse
opzioni di \texttt{psql} per indicare i parametri di connessione (utente,
password, ecc.) riportate nella seconda parte di tab.~\ref{tab:psql_options}.

Il secondo comando di gestione degli utenti è
\index{comando!\texttt{dropuser}} \texttt{dropuser} che consente di cancellare
un utente, da specificare come argomento, anche in questo caso si può
effettuare l'operazione su un server remoto con le stesse opzioni riportate
nella seconda parte di tab.~\ref{tab:psql_options}. Anche in questo caso si
tratta di un \textit{wrapper} alle relative istruzioni SQL, e per poterlo
usare senza dover eseguire una connessione esplicita occorrerà eseguirlo con
un utente di sistema in grado di collegarsi direttamente al database.

Una seconda coppia di comandi di gestione, \index{comando!\texttt{createdb}}
\texttt{createdb} e \index{comando!\texttt{dropdb}} \texttt{dropdb} consentono
rispettivamente di creare un nuovo database o rimuoverne uno esistente (con la
relativa perdita del contenuto). Entrambi prendono le opzioni della seconda
parte di tab.~\ref{tab:psql_options} per collegarsi ad un database
remoto. Inoltre \texttt{createdb} supporta l'uso dell'opzione \texttt{-O} che
consente di assegnare la proprietà del nuovo database ad un utente diverso da
quello con cui si esegue il comando, ovviamente posto che si abbiano i
privilegi necessari per farlo.

Infine uno dei comandi più importanti per la gestione sistemistica di
PostgreSQL è \index{comando!\texttt{pg\_dump}} \texttt{pg\_dump}, che consente
di esportare di tutti i dati di un database in un file di testo che conterrà
tutte le istruzioni SQL necessarie a ricreare, usando \texttt{psql} o un
qualunque altro client, su un database vuoto lo stesso contenuto di quello
esportato. Il comando crea quello che appunto viene chiamato un
``\textit{dump}'' del database, fornendo così il supporto sia per un backup
completo dei dati che per la conversione degli stessi in un formato portabile
che può essere riutilizzato anche con diverse versioni del software.

Se infatti è sempre possibile effettuare un backup dei dati andando a salvare
i file binari su cui PostgreSQL salva le informazioni, questi non è detto
siano in uno stato consistente, e soprattutto non è garantito, a meno di non
usare esattamente la stessa versione sulla stessa piattaforma hardware, che
essi possano essere riutilizzati direttamente. Un \textit{dump} con
\texttt{pg\_dump} assicura invece la riutilizzabilità dei dati anche fra
diverse versioni del server ed è sempre la modalità preferita per effettuare i
salvataggi dei dati di un database, considerazione che resta vera qualunque
sia il software che si usa (vale ad esempio anche per MySQL).

Il comando richiede come argomento il nome del database di cui si vuole
effettuare il ``\textit{dump}'', e supporta una serie di opzioni di controllo
per le modalità di creazione dello stesso.  Ad esempio con \texttt{-c} si
richiede che vengano inseriti nel \textit{dump} i comandi per cancellare il
database prima di ricrearlo, con \texttt{-f} si indica un file di uscita
invece dello \textit{standard output}. Sono inoltre supportate le opzioni per
gestire la connessione verso un server già riportate nella seconda parte di
tab.~\ref{tab:psql_options} ed una serie di ulteriori opzioni per eseguire il
salvataggio solo di alcune parti di dati.

Analogo a \texttt{pg\_dump} e con buona parte delle stesse opzioni, fra cui le
due citate in precedenza e quelle per il collegamento al server, è
\index{comando!\texttt{pg\_dumpall}} \texttt{pg\_dumpall} che invece di
eseguire il \textit{dump} di un database specifico lo effettua per tutti i
database presenti su un server, semplificando la gestione amministrativa dei
backup. Una opzione specifica è \texttt{-l} che consente di indicare il nome
del database di amministrazione interno su cui vengono mantenuti i dati
globali del server, come l'elenco degli altri database presenti e degli utenti
definiti internamente. In genere non è necessario indicarlo in quanto vengono
il default utilizza i nomi (\texttt{postgres} o \texttt{template1}) che
vengono creati automaticamente nell'installazione del servizio.

Occorre infine menzionare la possibilità, necessaria quando si vogliono usare
questi due ultimi comandi all'interno di uno script di backup eseguito in
batch che richieda l'uso di una connessione esplicita con autenticazione, di
usare il file \texttt{.pgpass} per evitare di dover immettere le password sul
terminale.  Infatti benché sia possibile usare delle variabili di ambiente per
le credenziali di connessione, queste non sono sicure perché possono essere
rilette da chiunque con \texttt{ps}.  Il file ha un formato generico che
prevede 5 campi separati da ``\texttt{:}'' nella forma:
\begin{Example}
hostname:port:database:username:password
\end{Example}
il cui significato è autoesplicativo, e si può usare il carattere jolly
``\texttt{*}'' quando non si intende specificare un valore per uno dei primi
quattro campi.  Il file deve essere mantenuto nella home directory dell'utente
che esegue i comandi e per garantire la sicurezza delle informazioni viene
ignorato se ha permessi di accesso per il gruppo o gli altri.


\subsection{Configurazione e gestione di base di MySQL}
\label{sec:sb_mysql}

MySQL è il \textit{database server} libero (disponibile con licenza GPL) più
diffuso,\footnote{anche grazie al fatto di aver potuto contare sulla
  promozione da parte dell'azienda che ne deteneva il codice e che vendeva
  licenze proprietarie per chi non voleva sottostare alle condizioni della
  GPL; oggi il codice è divenuto proprietà di Oracle, cosa che ha fatto
  sorgere qualche dubbio relativo al suo futuro sviluppo, essendo un chiaro
  concorrente dell'omonimo prodotto proprietario, tanto che ne viene
  sviluppata una versione completamente compatibile denominata MariaDB.} usato
da innumerevoli applicazioni Web, tanto da costituire la terza lettera
dell'acronimo \textit{LAMP}, che sta ad indicare, a seconda delle preferenze
di linguaggio del programmatore, la lista Linux, Apache, MySQL,
Perl/PHP/Python. Le sue caratteristiche sono la leggerezza e la semplicità di
amministrazione, ma ha solo una parte delle funzionalità disponibili con
PostgreSQL, anche se nella maggior parte dei casi queste sono sufficienti.

Come per PostgreSQL non tratteremo le modalità di installazione, essendo già
disponibili i relativi pacchetti in tutte le principali
distribuzioni.\footnote{nel caso di Debian il pacchetto si chiama
  \texttt{mysql-server} e fa parte della distribuzione ufficiale.} Anche MySQL
funziona adottando un modello client/server, in cui l'accesso ai dati viene
eseguito tramite un programma server (nel caso \index{demone!\texttt{mysqld}}
\texttt{mysqld}) cui si possono fare richieste con i relativi client, per
l'uso dei quali si dovranno installare i relativi pacchetti.

Il file di configurazione del server è
\index{configurazione!\texttt{/etc/mysql/my.cnf}} \texttt{/etc/mysql/my.cnf},
che contiene le direttive che ne controllano il funzionamento e che consentono
di ottimizzarne le prestazioni; il formato è quello dei file INI di Windows
(quello dei cosiddetti \textit{keyfile}, visto in
sez.~\ref{sec:cfg_general}). Per lo scopo introduttivo di questo paragrafo le
sole direttive di uso sistemistico che possono interessare sono quelle
relative alle modalità con cui il server può essere interrogato via rete, che
si trovano nella sezione marcata \texttt{[mysqld]}. Come per PostgreSQL il
default è ascoltare soltanto su \texttt{localhost} (per i concetti relativi
alle reti si rimanda al solito a sez.~\ref{sec:net_tcp_ip}) e se lo si vuol
rendere raggiungibile non solo in locale occorrerà inserire la direttiva:
\begin{Example}
bind_address = 0.0.0.0
\end{Example}

Le altre direttive consentono di specificare le directory ed i file usati dal
programma e l'utente per conto del quale deve essere eseguito, che nelle
versioni pacchettizzate già presenti nelle principali distribuzioni sono già
preimpostate a valori opportuni; l'unica altra che può essere significativa è
\texttt{port} che specifica la porta su cui il programma si può porre in
ascolto. Ulteriori importanti direttive di questa sezione sono quelle
attinenti alle dimensioni di memoria da assegnare a buffer e cache, la cui
trattazione però va oltre lo scopo di questo testo. 

Il comando principale per usare il database è \index{comando!\texttt{mysql}}
\texttt{mysql} che invoca il programma con cui ci si può connettere al
database. Se usato interattivamente le istruzioni devono essere inviate dal
prompt sul terminale, ma il comando può essere invocato anche in modalità non
interattiva, facendogli leggere le istruzioni da un file o con una redirezione
dello \textit{standard input}.  Il comando richiede in genere che si
specifichi un utente con l'opzione \texttt{-u} e se per questo utente è
prevista una password deve essere usata l'opzione \texttt{-p} per richiederne
l'immissione. Le altre opzioni principali sono riportate in
tab.~\ref{tab:mysql_options}, per l'elenco completo si consulti la pagina di
manuale.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-e \textsl{cmd}}  & esegue il comando passato come parametro (da
                                inserire come stringa) ed esce
                                immediatamente.\\
    \hline
    \texttt{-h \textsl{host}} & si collega all'indirizzo di rete passato come
                                parametro.\\ 
    \texttt{-P \textsl{port}} & si collega alla porta passata come parametro.\\
    \texttt{-u \textsl{user}} & si collega con l'utente passato come
                                parametro.\\  
    \texttt{-p}               & forza la richiesta della password utente prima
                                di collegarsi.\\  
    \hline
  \end{tabular}
  \caption{Le principali opzioni del comando \texttt{mysql}.}  
  \label{tab:mysql_options}
\end{table}

Il comando consente di specificare un argomento che indica il database a cui
ci si vuole collegare (fra quelli presenti sul server), perché questo sia
possibile occorre però che l'utente con il quale ci si collega abbia gli
opportuni privilegi di accesso. L'installazione di default prevede che sia
sempre presente un utente amministrativo generale (in genere viene usato il
nome \texttt{root} come per Unix) che ha accesso a tutti i database
presenti. 

Se non si specifica nessun argomento si accederà alla riga di comando senza
essere collegati a nessun database e si potrà eseguire il collegamento in una
fase successiva con il comando interno \texttt{use}; ad esempio per collegarsi
allo speciale database interno \texttt{mysql} che contiene tutti i dati
relativi alla gestione amministrativa del server si dovrà eseguire il comando:
\begin{Console}
mysql> \textbf{use mysql}
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
\end{Console}

Come per \texttt{psql} anche la riga di comando di \texttt{mysql} consente di
inviare specifici comandi di controllo preceduti dal carattere
``\texttt{\bslash}'', i principali dei quali sono riportati in
tab.~\ref{tab:mysql_control_command}, ma in questo caso ad essi sono in genere
associate anche delle esplicite parole chiave. Inoltre 

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|c|c|p{8cm}|}
    \hline
    \multicolumn{2}{|c|}{\textbf{Comando}} & \textbf{Significato} \\
    \hline
    \hline
    \verb|\u|&\texttt{use} & si connette a un database (da passare come
                             parametro).\\ 
    \verb|\q|&\texttt{quit}& esce dal programma.\\
    \verb|\!|&\texttt{system}& esegue il comando di shell passato come
                             parametro.\\ 
    \verb|\h|&\texttt{help}& stampa un riassunto dei comandi o la sintassi del
                             comando passato come argomento.\\ 
    \hline
  \end{tabular}
  \caption{Principali comandi di controllo di \texttt{mysql}.}  
  \label{tab:mysql_control_command}
\end{table}


A differenza di PostgreSQL non sono previsti comandi specifici per creare
utenti, per i quali si deve usare esplicitamente il linguaggio SQL per operare
sulla tabella \texttt{user} del database riservato \texttt{mysql} che contiene
tutti i dati relativi alla gestione amministrativa del server.\footnote{in
  realtà anche PostgreSQL mantiene i dati su una tabella interna, ma fornisce
  alcuni comandi che eseguono direttamente su di essa le operazioni necessarie
  alla gestione degli utenti senza dover ricorrere all'SQL.}

I comandi SQL in questione sono due, il più semplice è \texttt{CREATE USER}
che si limita alla creazione dell'utente, senza nessuna assegnazione di
permessi. Il comando richiede che si specifichi come ulteriore argomento un
nome utente. Questi nel caso di MySQL hanno un formato specifico nella forma:
\begin{Example}
'username'@'hostname'
\end{Example}
(gli apici sono necessari) in quanto ogni utente è associato anche ad una
macchina da cui questo può accedere via rete al server (si tratta dei campi
\texttt{user} e \texttt{host} della citata tabella \texttt{user}), per cui se
si vuole dare un accesso generico senza restrizioni relative alla macchina di
partenza, occorre specificarlo come \texttt{'username'@'\%'} usando il
carattere jolly ``\texttt{\%}'' del linguaggio SQL.

Se oltre a creare l'utente si intende pure assegnargli dei diritti di accesso
occorre invece utilizzare il comando SQL \texttt{GRANT}, seguito
dall'indicazione della lista dei privilegi come elenco di nomi separato da
virgole (ad esempio \texttt{SELECT,INSERT,UPDATE,DELETE,CREATE,INDEX,ALTER,
  ...}) oppure con l'indicazione generica \texttt{ALL PRIVILEGES}.

A questo deve seguire come argomento della parola chiave \texttt{ON}
l'indicazione del database o delle singole tabelle cui i privilegi si
applicano specificati come elenco separate da virgole nella forma
\texttt{nomedb.nometabella}, con la possibilità di usare la forma
\texttt{nomedb.*} per indicare un intero database.  Per indicare l'utente, che
verrà creato se non esistente, si deve poi aggiungere la parola chiave
\texttt{TO} seguita dal nome col formato appena illustrato.

Infine per l'impostazione di una password di accesso, che verrà mantenuta in
forma cifrata nel campo \texttt{password} della solita tabella \texttt{user},
entrambi i comandi prevedono l'uso di una ulteriore istruzione SQL
\texttt{IDENTIFIED BY} da aggiungere in coda al comando, con la password
specificata in chiaro fra virgolette. In questo caso un esempio val più di
mille parole, per cui si potranno creare degli utenti con una sintassi del
tipo:
\begin{Console}
mysql> \textbf{CREATE USER 'user1'@'localhost' IDENTIFIED BY 'pass1';}
Query OK, 0 rows affected (0.00 sec)

mysql> \textbf{GRANT ALL PRIVILEGES ON db.* TO 'user2'@'%' IDENTIFIED BY 'pass2';}
Query OK, 0 rows affected (0.00 sec)

mysql> 
\end{Console}

Nel caso di creazione di un database invece non è necessario ricorre all'uso
di comandi dedicati SQL (anche se questi comunque sono presenti) e si può
ricorrere al comando di amministrazione generale di MySQL
\index{comando!\texttt{mysqladmin}} \texttt{mysqladmin}, che viene usato per
anche per altre operazioni amministrative sul server. Il comando richiede che
si specifichi l'operazione da eseguire come primo argomento, seguita da
eventuali argomenti successivi e richiede la connessione al server con le
stesse opzioni di \texttt{mysql}, illustrate nella seconda parte di
tab.~\ref{tab:mysql_options}.

Per creare un database si deve usare l'operazione \texttt{create}, seguita dal
nome che si vuole dare al database stesso. Questo potrà essere anche
cancellato completamente con l'operazione \texttt{drop}, sempre seguita dal
nome.  Oltre a queste due, che sono le operazioni più comuni,
\texttt{mysqladmin} può essere usato per fermare e riavviare i processi del
database o per reimpostare la password dell'utente che si è usato per
collegarsi al server, per i dettagli si consulti la pagina di manuale.

Infine anche per MySQL è presente un opportuno comando di esportazione per i
contenuti di un database in istruzioni SQL registrate su un file di
testo,\index{comando!\texttt{mysqldump}} \texttt{mysqldump}. In questo il
comando prende come argomento il nome di un database seguito eventualmente da
una lista di tabelle se si vuole eseguire un \textit{dump} solo di alcune di
esse. Il comando riconosce inoltre l'opzione \texttt{-{}-all-database} che
esegue il \textit{dump} di tutti i database presenti sul server.

Si tenga presente che per l'uso di \texttt{mysqldump} negli script di backup a
differenza di PostgreSQL, per il quale si può avere un accesso senza password
usando un utente dedicato, è comunque necessario autenticarsi e fornire una
password, ed anche in questo caso, per gli stessi motivi di sicurezza già
detti, la modalità suggerita è quella di utilizzare il file di configurazione
delle opzioni di MySQL nella home dell'utente che esegue il backup che in
questo caso è \texttt{.my.cnf}.

Il formato del file è sempre quello dei file INI ed ha uno scopo molto più
generale in quanto serve da file di personalizzazione delle configurazioni
generico e può contenere direttive che riguardano anche il server, ma per lo
scopo specifico è sufficiente usare inserire la password che si vuole venga
utilizzata in una direttiva \texttt{password} nella sezione
\texttt{client}. In sostanza si dovrà avere un contenuto del tipo:
\begin{FileExample}[label=.my.cnf]
[client]
password=pwdsupersecret
\end{FileExample}



\subsection{Nozioni elementari di SQL}
\label{sec:sb_sql_lang}

Il linguaggio SQL (\textit{Structured Query Language}) nasce, come dice il
nome, come linguaggio per eseguire interrogazioni su una base di dati
relazionale.  Benché la sua conoscenza attenga più alle competenze di un
programmatore o di un amministratore di database, è opportuno anche per un
amministratore di sistema padroneggiare almeno le istruzioni più semplici di
questo linguaggio, data la sempre maggior diffusione dell'uso di database SQL
da parte di molti programmi.

Sta infatti diventando sempre più comune, anche grazie alla diffusione di
programmi come SQLite che consentono di mantenere un database relazionale su
semplici file, memorizzare dati di gestione (e talvolta anche configurazioni)
di un programma su un database di questo tipo per sfruttarne la velocità di
accesso nelle ricerche.  In questo caso molto spesso un amministratore di
sistema si trova nelle condizioni di dover intervenire ed eseguire delle
modifiche direttamente su tali dati, e per questo è necessaria una conoscenza
delle basi del linguaggio SQL.

Purtroppo, nonostante esista un certo livello di
standardizzazione,\footnote{il primo standard, realizzato dalla ANSI, è
  denominato SQL-86, ad esso sono seguite diverse revisioni, per un riassunto
  si legga \url{http://en.wikipedia.org/wiki/SQL\#Standardization}.} il
linguaggio SQL presenta innumerevoli varianti ed estensioni, nel nostro caso
ci limiteremo ad esaminare le forme più elementari che sono sostanzialmente le
stesse nelle varie implementazioni.  Inoltre quanto segue non è da
considerarsi minimamente una introduzione sistematica o formale a questo
linguaggio, ma soltanto un riassunto delle principali istruzioni ad uso di un
amministratore di sistema, orientate alla realizzazione di specifiche
operazioni come cercare informazioni o eseguire modifiche elementari
trascurando problematiche complesse come transazioni, atomicità, integrità
referenziale ecc.

Il linguaggio prevede l'uso di una serie di istruzioni che verranno eseguite
sul server per operare sui dati, dotate o meno di argomenti specifici, con
l'uso come separatore dello spazio e quello della virgola qualora gli
argomenti siano delle liste. In genere i valori numerici ed i nomi delle
colonne si usano direttamente mentre eventuali valori testuali devono essere
sempre immessi fra apici singoli.

Ogni comando SQL deve poi essere sempre terminato dal carattere ``\texttt{;}''
senza il quale l'uso del tasto di invio si limita a portare sulla riga
successiva dove si può continuare a scrivere come se si fosse aggiunto uno
spazio. Inoltre benché nella sintassi di SQL le istruzioni siano case
insensitive, per convenzione si tende a scriverle sempre in lettere maiuscole,
per distinguerle dai relativi argomenti e loro valori.

Il primo passo per l'uso del linguaggio è quello di ``\textsl{collegarsi}'' al
proprio database per eseguire i relativi comandi dalla console fornita dallo
stesso. Questo avviene, per i veri e propri \textit{database server}, con una
connessione (anche di rete) eseguita tramite un apposito programma client o,
come nel caso di SQLite, con un programma che opera direttamente sui file dei
dati. La sintassi per effettuare il collegamento varia ovviamente da programma
a programma, ed abbiamo visto nelle sezioni precedenti come fare per
PostgreSQL e MySQL. Nel caso si usi SQLite dato che ogni file è un database,
basterà eseguire un comando come \texttt{sqlite3 dbfile.sqlite}.

Una delle operazioni più comuni da effettuare su un database è quella relativa
alla ricerca dei dati. Trattandosi di database relazionale la struttura dei
dati è sempre in forma di tabelle, ed i dati devono essere cercati all'interno
delle stesse. Purtroppo non esiste una istruzione generica SQL per ottenere un
elenco delle tabelle di un database, ed ogni programma usa in genere comandi
diversi.

In realtà questi si riducono spesso alla ricerca dei dati all'interno di una
tabella di gestione interna, ma spesso questa ricerca viene
mascherata/semplificata fornendo alcuni comandi specifici della sintassi della
propria versione di SQL o del client usato per il collegamento. Esempi di
questi comandi sono ``\verb|\dt|'' in PostgreSQL, ``\texttt{show tables;}'' in
MySQL e ``\texttt{.tables}'' in SQLite, che consentono di ottenere un elenco
delle tabelle presenti nel database su cui si sta operando.

L'istruzione generica di ricerca dei dati è \texttt{SELECT}, che nella forma
più semplice deve essere seguita dalla lista delle colonne di cui si vogliono
ottenere i valori in forma di elenco di nomi separate da virgole, o
alternativamente, per ottenere i dati di tutte le colonne, dal carattere
``\texttt{*}'', a questa indicazione deve seguire l'istruzione \texttt{FROM},
seguita dal nome della tabella su cui si vuole effettuare la ricerca, con una
sintassi generica che viene usata anche da altre istruzioni del
linguaggio. Pertanto una delle modalità più comuni per esaminare il contenuto
di una tabella è eseguire il comando:
\begin{Example}
SELECT * FROM tablename;
\end{Example}
qualora invece si vogliano avere soltanto i valori di alcune colonne si dovrà
inserire l'elenco delle stesse, con un comando del tipo:
\begin{Example}
SELECT column1,column2 FROM tablename;
\end{Example}

L'uso delle due istruzioni precedenti comporta la stampa del contenuto di
tutte le righe (completo o solo per i valori delle colonne richieste)
contenute nella tabella. Se questa è grande si rischia di essere annegati nei
risultati, pertanto diventa utile poter richiedere un intervallo di dati. Per
questo la sintassi di SQL per \texttt{SELECT} prevede la possibilità di
aggiungere la istruzione \texttt{LIMIT} che consente di indicare un numero di
righe da restituire, sintassi che si può usare anche per altre istruzioni che
prevedono di operare su un numero qualunque di righe.

Se non si specifica altro verranno restituite le prime righe della tabella, ma
si può indicare un diverso punto di partenza usando la ulteriore istruzione
\texttt{OFFSET} che indica una riga di partenza, inoltre molti programmi
supportano anche una notazione compatta che consente di indicare direttamente
con \texttt{LIMIT} un punto di partenza ed un numero di righe indicando
l'argomento con due numeri nella forma \texttt{offs,rows}. Se allora si
vogliono vedere le prime 10 righe di una tabella si dovrà usare un comando del
tipo:
\begin{Example}
SELECT * FROM tablename LIMIT 10;
\end{Example}

Una modalità diversa per restringere l'elenco dei risultati è quella di
ricorrere all'istruzione \texttt{WHERE} che consente di selezionare le righe
restituite in base ad una condizione sui valori assunti da una qualunque
colonna, che in genere viene espressa nella forma più elementare come
\texttt{nomecolonna='valore'} per richiedere la corrispondenza ad un certo
valore. Pertanto per ottenere le righe in cui \texttt{column2} ha il valore
\texttt{value} si dovrà usare un comando del tipo:
\begin{Example}
SELECT * FROM tablename WHERE column2='value';
\end{Example}

La forma illustrata nel precedente esempio è quella più semplice in cui si
richiede una semplice uguaglianza, ma sono supportate anche sintassi più
elaborate, con operatori come ``\texttt{>}'', ``\texttt{>=}'', ``\texttt{<}'',
``\texttt{<=}'' e la parola chiave \texttt{LIKE} che consente di indicare un
pattern analogo a quello del \textit{filename globbing} dove il ruolo del
carattere jolly viene però volto da ``\texttt{\%}'', invece che
dall'asterisco. 

Sono poi supportate anche la negazione di una condizione con la parola chiave
\texttt{NOT} e combinazioni logiche di più condizioni con le parole chiave
\texttt{OR} e \texttt{AND} e l'uso delle ordinarie parentesi tonde.  Si tenga
presente che questa sintassi dell'istruzione \texttt{WHERE} è generica, e si
ritrova identica anche nella sintassi di altre istruzioni, come
\texttt{DELETE} e \texttt{UPDATE}, dove come per \texttt{SELECT} viene usata
per selezionare le righe su cui operare con un opportuno criterio di
corrispondenza.

L'ultima estensione della sintassi di \texttt{SELECT} che vedremo è quella che
consente di ottenere una lista di risultati opportunamente indicizzata. Per
questo si deve ricorrere alla ulteriore istruzione \texttt{ORDER BY} che
consente di richiedere un ordinamento dei dati sulla base dei valori dei campi
indicati di seguito, e se ne possono specificare più di uno per avere
ordinamenti progressivi su più campi. Inoltre si può chiedere un ordinamento
discendente o ascendente (ma quest'ultimo è il default), rispettivamente con
le ulteriori parole chiave \texttt{DESC} e \texttt{ASC}. Un esempio in questo
caso sarebbe qualcosa del tipo:
\begin{Example}
SELECT * FROM tablename ORDER BY column2;
\end{Example}

La seconda operazione amministrativa che capita di dover effettuare molto
spesso su un database è quella di modificare il valore di un dato in una
qualche tabella. In questo caso l'istruzione da usare è \texttt{UPDATE}
seguita dal nome della tabella su cui si intende operare, a cui poi deve
seguire l'istruzione \texttt{SET} per indicare su quale colonna si vuole
operare e quale è il valore da impostare, che dovrà essere indicato nella
forma \texttt{nomecolonna='valore'}. In genere il linguaggio consente di
modificare in contemporanea i valori di più colonne, semplicemente indicando
più assegnazioni come la precedente separate da virgole.

L'uso di queste due istruzioni è sufficiente per avere un comando SQL
corretto, ma l'effetto normalmente non è quello desiderato, dato che in questo
caso si cambierebbero i valori per tutte le righe della colonna, cosa che
raramente è quello che si vuole ed è invece un errore abbastanza
frequente. Per questo anche se il resto è opzionale nella sintassi, il comando
in genere deve essere completato con la ulteriore istruzione \texttt{WHERE}
che indichi la riga o le righe su cui si vuole operare.  Per questo il comando
tipo che consente di cambiare il valore di un dato mantenuto nella colonna
\texttt{column1} per la riga in cui si ha uno specifico valore di
\texttt{column2} è qualcosa del tipo:
\begin{Example}
UPDATE tablename SET column1='newvalue' WHERE column2='identifier';
\end{Example}

Ma si rammenti che anche in questo caso se si vuole cambiare il valore di una
unica riga si deve essere sicuri che la selezione effettuata con
\texttt{WHERE} dia un risultato unico, perché altrimenti verranno cambiati i
valori di \texttt{column1} per tutte le righe che corrispondono alla
condizione su \texttt{column2}, si può però riutilizzare l'istruzione
\texttt{LIMIT} per porre un limite sul numero di righe che verranno
modificate.

Con \texttt{UPDATE} si possono modificare i valori presenti in una tabella, ma
non se ne possono aggiungere di nuovi, per questo infatti occorre un'altra
istruzione, \texttt{INSERT}, che serve ad inserire nuovi record (righe) in una
tabella. La tabella deve essere indicata con il nome dopo l'ulteriore parola
chiave \texttt{INTO}, mentre per indicare i valori da inserire esistono due
sintassi alternative.

La prima alternativa prevede che si fornisca l'elenco dei valori da inserire
nella riga come elenco di valori, separati da virgole e compresi fra parentesi
tonde, che deve seguire l'ulteriore istruzione \texttt{VALUES}. In questo caso
i valori verranno inseriti sequenzialmente nelle colonne della tabella, ed il
loro numero deve corrispondere a quello delle colonne. Un esempio di questa
sintassi potrebbe essere il comando:
\begin{Example}
INSERT INTO tablename  VALUES ('val1', 'val2', 'val3', 'val4');
\end{Example}

La seconda alternativa consente di indicare i valori da assegnare alle singole
colonne, lasciando anche alcune vuote. In questo caso occorrerà fornire prima
di \texttt{VALUES} l'elenco delle colonne, elencate per nomi separati da
virgole e racchiusi in parentesi tonde, e poi far seguire l'elenco dei valori,
in numero corrispondente a quello delle colonne, che ad esse verranno
rispettivamente assegnati. Un esempio di questa sintassi potrebbe essere il
comando:
\begin{Example}
INSERT INTO tablename (column1, column3) VALUES ('val1', 'val3');
\end{Example}

Un'altra operazione comune, dopo modifica ed inserimento, è quella di
cancellazione, che viene eseguita attraverso l'istruzione \texttt{DELETE}
seguita dall'indicazione della tabella su cui operare preceduta dalla
ulteriore parola chiave \texttt{FROM}. A questa segue normalmente una
ulteriore istruzione \texttt{WHERE} per indicare quale righe cancellare, dato
che altrimenti verrebbero cancellati tutti i contenuti della tabella, cosa che
è raramente quello che si vuole. Di nuovo il comando cancellerà tutte le righe
selezionata con \texttt{WHERE} per cui può essere opportuno controllare con
una \texttt{SELECT} preventiva, che ha esattamente la stessa sintassi, cosa si
va cancellare. Un esempio potrebbe essere il comando:
\begin{Example}
DELETE FROM tablename WHERE column2='value';
\end{Example}

Infine, ancorché molto più specialistica, un'ultima istruzione che può
risultare utile è \texttt{JOIN} che consente di unire i dati di due tabelle
usando un campo comune, in sostanza qualcosa di simile a quello che fa il
comando \texttt{join} visto in sez.~\ref{sec:cmd_file_filter}. In sostanza con
\texttt{JOIN} si possono sfruttare le capacità relazionali del database e fare
ricerche unendo i dati che si sono suddivisi sulle varie tabelle usando ad
esempio le \textit{foreign key} di cui si è parlato in
sez.~\ref{sec:sb_relational_database}.

La sintassi prevede che \texttt{JOIN} venga usato come estensione di una
\texttt{SELECT}, indicando come argomento il nome della tabella di cui si
vuole effettuare la ``\textsl{giunta}'' seguita dalla ulteriore parola chiave
\texttt{ON} che indica quali sono i campi che devono corrispondere, da
indicare nella notazione \texttt{tabA.colA=tabB.colB}. In questo caso la
\texttt{SELECT} deve indicare, con la stessa notazione \texttt{tabN.colN}
quali campi delle due tabelle si vogliono ottenere, e verranno restituiti in
una unica riga i dati presenti nelle due tabelle per cui le colonne indicate
hanno lo stesso valore.

In sostanza se i valori di una colonna di una tabella, in genere un
identificativo univoco, sono usati come valori per un'altra colonna in un
altra tabella, che contiene altri dati relativi a questo identificativo, si
può generare una lista di tutte le possibili corrispondenze. Nell'esempio di
autori e libri cui si è accennato in sez.~\ref{sec:sb_relational_database}
allora, posto che si sia usato una colonna con un identificativo unico (una
\textit{primary key}, diciamo nella colonna \texttt{id\_autore}) nella tabella
degli autori e che si sia usato lo stesso identificativo dell'autore nella
tabella dei libri (come \textit{foreign key}, diciamo nella colonna
\texttt{autore}) si potrà ottenere una lista di tutti i libri e tutti gli
autori con un comando del tipo:
\begin{Example}
SELECT autori.nome, autori.cognome, libri.titolo, libri.editore 
FROM autori JOIN libri
ON autori.id_autore=libri.autore;
\end{Example}

In realtà il comando prevede diverse varianti, anche se quella più comune è
quella illustrata che viene più precisamente indicata come \texttt{INNER
  JOIN}. Per maggiori dettagli si rimanda ad un qualunque testo elementare che
tratti le basi dell'SQL o alla documentazione dei principali server di
database. 



% LocalWords:  filesystem sez var home usr SCSI tar ARchive tab extract list Di
% LocalWords:  diff update append delete get cvf tex advadmin config fdl shell
% LocalWords:  netadmin netbase netinter ordadmin CVS images pathname cf is the
% LocalWords:  archive not dumped ls vfat Windows cpio copy find filename pass
% LocalWords:  globbing through NUL dump restore ext journalled fstab mount gz
% LocalWords:  point inode multivolume tarball tgz gzip bzip bz mirror xvzf dev
% LocalWords:  README INSTALL configure make install report PATH clean
% LocalWords:  unistall rpm RedHat Package upgrade qa qf qpf l'upgrade ql hell
% LocalWords:  dependency APT Advanced Tool deb dpkg dall' apt dell' repository
% LocalWords:  FTP debconf remove purge dist autoclean kernel multitutente like
% LocalWords:  username groupname pag Name Service Switch Pluggable PAM Modules
% LocalWords:  Authentication NIS LDAP useradd passwd shadow usermod groupadd
% LocalWords:  group groupmod userdel groupdel adduser addgroup deluser gpasswd
% LocalWords:  delgroup l'username newgrp sg chsh chfn Gecos ps hash root admin
% LocalWords:  DES pippo ciccio daemon bin sys sync games tty pwconv MIN DAYS
% LocalWords:  WARN defs grpconv pwunconv grpunconv getent Solaris auth session
% LocalWords:  type control module path arguments pam required sufficient first
% LocalWords:  try expose authtok service adm prefix ac qpl checksig GPG src of
% LocalWords:  whatprovides whatrequires URL stable testing unstable sid main
% LocalWords:  contrib security users last getty PPC hostname telnet ssh motd
% LocalWords:  message yes consoles Same as above but these only occur cp dd if
% LocalWords:  with devfs devices vc bashrc bash profile chage YYYY DD nologin
% LocalWords:  replacefiles replacepkg soldpackage force Piccardi Bacula Amanda
% LocalWords:  BackupPC disk DVD DLT DAT USB GNU default output stardard TODO
% LocalWords:  postinst alien who fontsize xleftmargin version published by Srl
% LocalWords:  xrightmargin piccardi AGE login.defs NSS Free Foundation Texts
% LocalWords:  frame single samepage true chpasswd chgpasswd UMASK CMD debug If
% LocalWords:  use mapped Invariant Sections Front-Cover and Back-Cover license
% LocalWords:  included section entitled Documentation Jan ordadmin.tex input
% LocalWords:  incremental differential operation general options classes this
% LocalWords:  Permission granted distribute modify document under terms any db
% LocalWords:  later retention snapshot tool gcc Compiler Collection build all
% LocalWords:  essential Makefile Hierarchy freshen erase nodeps query verify
% LocalWords:  setperms setugids package yum aptitude sources CDROM cdrom add
% LocalWords:  NFS ftp Toy Story etch lenny Ubuntu hardy restricted universe bs
% LocalWords:  multiverse Official NETINST Binary updates nomepacchetto fig org
% LocalWords:  reinstall hold unhold forbid safe search cache policy depends Kb
% LocalWords:  rdepends showpkg RHEL backports salt live glibc Information you
% LocalWords:  Lightweight Access Protocol Example configuration functionality
% LocalWords:  have packages installed info libc for information about compat
% LocalWords:  hosts files dns networks protocols services ethers rpc netgroup
% LocalWords:  nis aliases MAC address lib libnss ldap kilobyte count skip seek
% LocalWords:  obs ibs rsync exclude GID UID compress program blocks depth ini
% LocalWords:  print wildcard available extras CentOS cachedir keepcache newest
% LocalWords:  debuglevel logfile pkgpolicy distroverpkg redhat tolerant expire
% LocalWords:  exactarch obsoletes gpgcheck plugins metadata old reconfigure to
% LocalWords:  stradmin usbkey img Yellowdog Updater Modified proxy reposdir
% LocalWords:  repo conf addons centosplus name baseurl mirrorlist gpgkey suid
% LocalWords:  enabled RESTRICT replacepkgs oldpackage dall'APT syslog facility
% LocalWords:  cmd dall'username dall'UID timestamp sudoedit userspace Backus
% LocalWords:  Naur EBNF Form altroutente tag NOPASSWD SETENV NOSETENV EXEC env
% LocalWords:  NOEXEC Host Runas Defaults reset LOGNAME keep setenv off tries
% LocalWords:  visudo authpriv apachectl MUST edited command See page details
% LocalWords:  how write sudoers webmaster Cmnd privilege specification LEN kde
% LocalWords:  securetty LIBRARY logout mozilla smart other success ignore new
% LocalWords:  reqd unknown types bad die done common substack log nullok sha
% LocalWords:  secure min remember issue limits built ulimit soft limit fork
% LocalWords:  bomb domain value fsize nofile cpu nproc maxlogins maxsyslogins
% LocalWords:  nice student maxlogin cracklib minlen difok listfile rhost MySQL
% LocalWords:  ruser sense allow deny Administrator SQL subselect rsh DBA NoSQL
% LocalWords:  trigger foreign key Oracle LAMP Perl Structured Language SQLite
% LocalWords:  Standardization client sqlite PostgreSQL BerkleyDB tuple field
% LocalWords:  attributes null primary relation RDBMS Relational System listen
% LocalWords:  postmaster postgresql addresses local socket host CIDR ident
% LocalWords:  sameuser postgres administrative sockets METHOD connections psql
% LocalWords:  wrapper ROLE createuser createdb mysql mysqld localhost bind
% LocalWords:  mysqladmin mysqldump SELECT insensitive FROM autotools linker
% LocalWords:  LIBS exec yumdownloader destdir source Scientific basearch can
% LocalWords:  releasever installonly squeeze wheezy lucid superuser dropuser
% LocalWords:  dropdb port Reading table completion column names turn feature
% LocalWords:  quicker startup changed quit system tablename WHERE pg dumpall
% LocalWords:  template GRANT INSERT INDEX PRIVILEGES IDENTIFIED rows sec ASC
% LocalWords:  affected LDFLAGS pgpass nomedb ORDER DESC INTO VALUES JOIN
% LocalWords:  join INNER CFLAGS CPPFLAGS tables

%%% Local Variables: 
%%% mode: latex
%%% TeX-master: "corso"
%%% End: 
 
