Iserita syslog
[gapil.git] / session.tex
index 6d572a22a3e0f20b8aeae8526cf74051d55ab9ad..b2115ac173a167856399ca84616c0d6cc062f59e 100644 (file)
@@ -571,106 +571,68 @@ ripetere da capo tutto il procedimento.
 Come sottolineato fin da \secref{sec:intro_base_concept}, in un sistema
 unix-like tutte le operazioni sono eseguite tramite processi, comprese quelle
 operazioni di sistema (come l'esecuzione dei comandi periodici, o la consegna
-della posta, ed in generale tutti i programmi di servizio) che non hanno a che
-fare con la gestione diretta dei comandi dell'utente.
+della posta, ed in generale tutti i programmi di servizio) che non hanno
+niente a che fare con la gestione diretta dei comandi dell'utente.
 
 Questi programmi, che devono essere eseguiti in modalità non interattiva e
 senza nessun intervento dell'utente, sono normalmente chiamati
 \textsl{demoni}, (o \textit{daemons}), nome ispirato dagli omonimi spiritelli
-che svolgevano vari compiti, di cui parlava Socrate (che sosteneva di averne
+che svolgevano compiti vari, di cui parlava Socrate (che sosteneva di averne
 uno al suo servizio).\footnote{NdT. ricontrollare, i miei ricordi di filosofia
-  sono piuttosto datati.} 
-
-Nei sistemi che supportano il \textit{job control} eseguire un programma da
-riga di comando comporta che esso venga associato ad un terminale di controllo
-e mantenuto all'interno di una sessione, e anche se può essere mandato in
-background e non eseguire nessun I/O su terminale, si avranno comunque tutte
-le conseguenze che abbiamo appena visto in \secref{sec:sess_ctrl_term} (in
-particolare all'uscita del leader di sessione). 
-
-Per questo motivo un programma che deve funzionare come demone deve prendere
-da solo i provvedimenti opportuni (come distaccarsi dal terminale e dalla
-sessione) ad impedire interferenze da parte del sistema del \textit{job
-  contol}; questi sono riassunti in una lista di prescrizioni\footnote{ad
-  esempio sia Stevens in \cite{APUE}, che la \textit{Unix Programming FAQ}
-  \cite{UnixFAQ} ne riportano di sostanzialmente identiche.} da seguire quando
-si scrive un demone.
+  sono piuttosto datati.}
+
+Se però si lancia un programma demone dalla riga di comando in un sistema che
+supporta, come Linux, il \textit{job control} esso verrà comunque associato ad
+un terminale di controllo e mantenuto all'interno di una sessione, e anche se
+può essere mandato in background e non eseguire più nessun I/O su terminale,
+si avranno comunque tutte le conseguenze che abbiamo appena visto in
+\secref{sec:sess_ctrl_term} (in particolare l'invio dei segnali in
+corrispondenza dell'uscita del leader di sessione).
+
+Per questo motivo un programma che deve funzionare come demone deve sempre
+prendere autonomamente i provvedimenti opportuni (come distaccarsi dal
+terminale e dalla sessione) ad impedire eventuali interferenze da parte del
+sistema del \textit{job contol}; questi sono riassunti in una lista di
+prescrizioni\footnote{ad esempio sia Stevens in \cite{APUE}, che la
+  \textit{Unix Programming FAQ} \cite{UnixFAQ} ne riportano di sostanzialmente
+  identiche.} da seguire quando si scrive un demone.
 
 Pertanto, quando si lancia un programma che deve essere eseguito come demone
-occorrerà che esso compia le seguenti azioni:
+occorrerà predisporlo in modo che esso compia le seguenti azioni:
 \begin{enumerate}
 \item Eseguire una \func{fork} e terminare immediatamente il processo padre
   proseguendo l'esecuzione nel figlio.  In questo modo si ha la certezza che
-  il processo non è un \textit{process group leader}, e si può chiamare
-  \func{setsid} con successo.
-\item Eseguire \func{setsid} per creare un nuovo raggruppamento ed una nuova
-  sessione di cui il processo è leader, e che non ha associato nessun
-  terminale di controllo.
-\item Assicurarsi che al processo non venga associato nessun nuovo terminale
-  di controllo; questo può essere fatto sia avendo cura di usare sempre
-  l'opzione nell'aprire i file, che eseguendo una ulteriore \func{fork}
-  proseguendo nel figlio, che a questo punto non essendo più leader di
-  sessione non può più ottenere un terminale di controllo. 
-\item Eseguire una \func{chdir} per impostare la directory di lavoro (su
-  \file{/} o su una directory che contenga dei file necessari per il
-  programma), per evitare che la directory da cui si è lanciato il processo
+  il figlio non è un \textit{process group leader}, (avrà il \acr{pgid} del
+  padre, ma un \acr{pid} diverso) e si può chiamare \func{setsid} con
+  successo. Inoltre la shell considererà terminato il comando all'uscita del
+  padre.
+\item Eseguire \func{setsid} per creare una nuova sessione ed un nuovo
+  raggruppamento di cui il processo diventa automaticamente il leader, che
+  però non ha associato nessun terminale di controllo.
+\item Assicurarsi che al processo non venga associato in seguito nessun nuovo
+  terminale di controllo; questo può essere fatto sia avendo cura di usare
+  sempre l'opzione \macro{O\_NOCTTY} nell'aprire i file di terminale, che
+  eseguendo una ulteriore \func{fork} uscendo nel padre e proseguendo nel
+  figlio. In questo caso, non essendo più quest'ultimo un leader di sessione
+  non potrà ottenere automaticamente un terminale di controllo.
+\item Eseguire una \func{chdir} per impostare la directory di lavoro del
+  processo (su \file{/} o su una directory che contenga dei file necessari per
+  il programma), per evitare che la directory da cui si è lanciato il processo
   resti in uso e non sia possibile rimuoverla o smontare il filesystem che la
   contiene.
 \item Impostare la maschera dei permessi (di solito con \code{umask(0)}) in
   modo da non essere dipendenti dal valore ereditato da chi ha lanciato
   originariamente il processo. 
-\item Chiudere i file standard (o redirigerli verso \file{/dev/null}).
+\item Chiudere tutti i file aperti che non servono più (in generale tutti); in
+  particolare vanno chiusi i file standard che di norma sono ancora associati
+  al terminale (un'altra opzione è quella di redirigerli verso
+  \file{/dev/null}).
 \end{enumerate}
 
 
-In Linux buona parte di queste azioni, possono venire eseguite invocando la
+In Linux buona parte di queste azioni possono venire eseguite invocando la
 funzione \func{daemon}, introdotta per la prima volta in BSD4.4; il suo
 prototipo è:
-\begin{prototype}{unistd.h}{pid\_t getsid(pid\_t pid)}
-  Legge l'identificatore di sessione del processo \param{pid}.
-  
-  \bodydesc{La funzione restituisce l'identificatore (un numero positivo) in
-  caso di successo, e -1 in caso di errore, nel qual caso \var{errno} assumerà
-  i valori:
-    \begin{errlist}
-    \item[\macro{ESRCH}] Il processo selezionato non esiste.
-    \item[\macro{EPERM}] In alcune implementazioni viene restituito quando il
-      processo selezionato non fa parte della stessa sessione del processo
-      corrente.
-    \end{errlist}
-  }
-\end{prototype}
-
-Entrambi gli identificatori vengono inizializzati alla creazione di ciascun
-processo con lo stesso valore che hanno nel processo padre, per cui un
-processo appena creato appartiene sempre allo stesso raggruppamento e alla
-stessa sessione del padre. Vedremo poi come sia possibile creare più
-\textit{process group} all'interno della stessa sessione, e spostare i
-processi dall'uno all'altro, ma sempre all'interno di una stessa sessione.
-
-Ciascun raggruppamento di processi ha sempre un processo principale, il
-cosiddetto \textit{process group leader}, che è identificato dall'avere un
-\acr{pgid} uguale al suo \acr{pid}, in genere questo è il primo processo del
-raggruppamento, che si incarica di lanciare tutti gli altri. Un nuovo
-raggruppamento si crea con la funzione \func{setpgrp},\footnote{questa è la
-  definizione di POSIX.1, BSD definisce una funzione con lo stesso nome, che
-  però è identica a \func{setpgid}; nelle \acr{glibc} viene sempre usata
-  sempre questa definizione, a meno di non richiedere esplicitamente la
-  compatibilità all'indietro con BSD, definendo la macro
-  \macro{\_BSD\_SOURCE}.} il cui prototipo è:
-\begin{prototype}{unistd.h}{int setpgrp(void)}
-  Modifica il \acr{pgid} al valore del \acr{pid} del processo corrente.
-  
-  \bodydesc{La funzione restituisce il valore del nuovo \textit{process
-      group}.}
-\end{prototype}
-
-La funzione, assegnando al \acr{pgid} il valore del \acr{pid} processo
-corrente, rende questo \textit{group leader} di un nuovo raggruppamento, tutti
-i successivi processi da esso creati apparterranno (a meno di non cambiare di
-nuovo il \acr{pgid}) al nuovo raggruppamento. È possibile invece spostare un
-processo da un raggruppamento ad un altro con la funzione \func{setpgid}, il
-cui prototipo è:
 \begin{prototype}{unistd.h}{int daemon(int nochdir, int noclose)}
   Esegue le operazioni che distaccano il processo dal terminale di controllo e
   lo fanno girare come demone.
@@ -680,11 +642,203 @@ cui prototipo 
     valori impostati dalle sottostanti \func{fork} e \func{setsid}.}
 \end{prototype}
 
-La funzione esegue una \func{fork}, per uscire subito, con \func{\_exit} nel
-padre, mentre l'esecuzione prosegue nel figlio che esegue \func{setsid}. Se
-\param{nochdir} è nullo la funzione importa anche la directory di lavoro su
-\file{/}, se \param{noclose} è nullo i file standard vengono rediretti su
-\file{dev/null}.
+La funzione esegue una \func{fork}, per uscire subito, con \func{\_exit}, nel
+padre, mentre l'esecuzione prosegue nel figlio che esegue subito una
+\func{setsid}. In questo modo si compiono automaticamente i passi 1 e 2 della
+precedente lista. Se \param{nochdir} è nullo la funzione imposta anche la
+directory di lavoro su \file{/}, se \param{noclose} è nullo i file standard
+vengono rediretti su \file{/dev/null} (corrispondenti ai passi 4 e 6); in caso
+di valori non nulli non viene eseguita nessuna altra azione.
+
+Dato che un programma demone non può più accedere al terminale, si pone il
+problema di come fare per la notifica di eventuali errori, non potendosi più
+utilizzare lo standard error; per il normale I/O infatti ciascun demone avrà
+le sue modalità di interazione col sistema e gli utenti a seconda dei compiti
+e delle funzionalità che sono sono previste; ma gli errori devono normalmente
+essere notificati all'amministratore del sistema.
+
+Una soluzione può essere quella di scrivere gli eventuali messaggi su uno
+specifico file (cosa che a volte viene fatta comunque) ma questo comporta il
+grande svantaggio che l'amministratore dovrà tenere sotto controllo un file
+diverso per ciascun demone, e che possono anche generarsi conflitti di nomi.
+Per questo in BSD4.2 venne introdotto un servizio di sistema, il
+\textit{syslog}, che oggi si trova su tutti i sistemi Unix, e che permettesse
+ai demoni di inviare messaggi all'amministratore in una maniera
+standardizzata.
+
+Il servizio prevede vari meccanismi di notifica, e, come ogni altro servizio
+in un sistema unix-like, viene gestito attraverso un apposito programma,
+\cmd{syslogd}, che è anch'esso un \textsl{demone}. In generale i messaggi di
+errore vengono raccolti dal file speciale \file{/dev/log}, un \textit{socket}
+locale (vedi \secref{sec:sock_sa_local}) dedicato a questo scopo, o via rete,
+con un \textit{socket} UDP, o da un apposito demone, \cmd{klogd}, che estrae i
+messaggi del kernel.\footnote{i messaggi del kernel sono tenuti in un buffer
+  circolare e scritti tramite la funzione \func{printk}, analoga alla
+  \func{printf} usata in user space; una trattazione eccellente dell'argomento
+  si trova in \cite{LinDevDri}, nel quarto capitolo.}
+
+Il servizio permette poi di trattare i vari messaggi classificandoli
+attraverso due indici; il primo, chiamato \textit{facility}, indica quale
+categoria di demone ha emesso il messaggio, ed è organizzato in sottosistemi
+(kernel, posta elettronica, demoni di stampa, ecc.), il secondo, chiamato
+\textit{priority}, identifica l'importanza del messaggio. Il sistema di
+\textit{syslog} provvede poi a riportare i messaggi all'amministratore
+attraverso differenti meccanismi come:
+\begin{itemize*}
+\item scrivere sulla console.
+\item inviare via mail ad uno specifico utente.
+\item scrivere su un file (comunemente detto \textit{log file}).
+\item inviare ad un altro demone (anche via rete).
+\item scartare.
+\end{itemize*}
+secondo le modalità che questo preferisce e che possono essere impostate
+attraverso il file di configurazione \file{/etc/syslog.conf} (maggiori
+dettagli si possono trovare sulle pagine di manuale per questo file e per
+\cmd{syslogd}).
+
+Le \acr{glibc} definiscono una serie di funzioni standard con cui un processo
+può accedere in maniera generica al servizio di syslog, che però funzionano
+solo localmente; se si vogliono inviare i messaggi ad un'altro sistema occorre
+farlo esplicitamente con un socket UDP, o utilizzare le capacità di reinvio
+del servizio.
+
+La prima funzione definita dall'interfaccia è \func{openlog}, che apre una
+connessione al servizio di \textit{syslog}; essa in generale non è necessaria
+per l'uso del servizio, ma permette di impostare alcuni valori che controllano
+gli effetti delle chiamate successive; il suo prototipo è:
+\begin{prototype}{syslog.h}{void openlog(const char *ident, int option, 
+int facility)}
+
+Apre una connessione al sistema di \textit{syslog}.
+  
+\bodydesc{La funzione non restituisce nulla.}
+\end{prototype}
+
+La funzione permette di specificare, tramite \param{ident}, l'identità di chi
+ha inviato il messaggio (di norma si passa il nome del programma, come
+specificato da \code{argv[0]}); la stringa verrà preposta all'inizio di ogni
+messaggio. Si tenga presente che il valore di \param{ident} che si passa alla
+funzione è un puntatore, se la stringa cui punta viene cambiata lo sarà pure
+nei successivi messaggi, e se viene cancellata i risultati potranno essere
+impredicibili, per questo è sempre opportuno usare una stringa costante. Il
+parametro \param{facility} permette invece di specificare l'omonimo indice per
+la categoria del messaggio; i valori possibili sono riportati in
+\tabref{tab:sess_syslog_facility}.
+
+\begin{table}[htb]
+\centering
+\begin{tabular}[c]{|l|p{8cm}|}
+\hline
+\textbf{Valore}& \textbf{Significato}\\
+\hline
+\hline
+\macro{LOG\_AUTH}     & Messaggi relativi ad autenticazione e sicurezza,
+                        obsoleto, è sostituito da \macro{LOG\_AUTHPRIV}. \\
+\macro{LOG\_AUTHPRIV} & Sostituisce \macro{LOG\_AUTH}.\\
+\macro{LOG\_CRON}     & Messaggi dei demoni di gestione dei comandi
+                        programmati (\cmd{cron} e \cmd{at}).\\
+\macro{LOG\_DAEMON}   & Demoni di sistema.\\
+\macro{LOG\_FTP}      & Server FTP.\\
+\macro{LOG\_KERN}     & Messaggi del kernel\\
+\macro{LOG\_LOCAL0}   & Riservato all'amministratore per uso locale\\
+--- & \\
+\macro{LOG\_LOCAL7}   & Riservato all'amministratore per uso locale\\
+\macro{LOG\_LPR}      & Messaggi del sistema di gestione delle stampanti \\
+\macro{LOG\_MAIL}     & Messaggi del sistema di posta elettronica\\
+\macro{LOG\_NEWS}     & Messaggi del sistema di gestione delle news (USENET) \\
+\macro{LOG\_SYSLOG}   & Messaggi generati dallo stesso \cmd{syslogd}\\
+\macro{LOG\_USER}     & Messaggi generici a livello utente\\
+\macro{LOG\_UUCP}     & Messaggi del sistema UUCP\\
+\hline
+\end{tabular}
+\caption{Valori possibili per l'argomento \param{facility} di \func{openlog}.}
+\label{tab:sess_syslog_facility}
+\end{table}
+
+L'argomento \param{option} serve invece per controllare il comportamento della
+funzione \func{openlog} e delle modalità con cui le successive chiamate
+scriveranno i messaggi, esso viene specificato come maschera binaria composta
+con un OR aritmetico di una qualunque delle costanti riportate in
+\tabref{tab:sess_openlog_option}.
+
+\begin{table}[htb]
+\centering
+\begin{tabular}[c]{|l|p{8cm}|}
+\hline
+\textbf{Valore}& \textbf{Significato}\\
+\hline
+\hline
+\macro{LOG\_CONS}   & Scrive sulla console quando. \\
+\macro{LOG\_NDELAY} & Sostituisce \macro{LOG\_AUTH}.\\
+\macro{LOG\_NOWAIT} & Messaggi dei demoni di gestione dei comandi
+                      programmati (\cmd{cron} e \cmd{at}).\\
+\macro{LOG\_ODELAY} & .\\
+\macro{LOG\_PERROR} & Stampa anche su \file{stderr}.\\
+\macro{LOG\_PID}    & Inserisce nei messaggi il \acr{pid} del processo
+                      chiamante. \\
+\hline
+\end{tabular}
+\caption{Valori possibili per l'argomento \param{option} di \func{openlog}.}
+\label{tab:sess_openlog_option}
+\end{table}
+
+La funzione che si usa per generare un messaggio è \func{syslog}, dato che
+l'uso di \func{openlog} è ozionale, sarà quest'ultima a provvede a chiamare la
+prima qualora ciò non sia stato fatto (nel qual caso il valore di
+\param{ident} è nullo). Il suo prototipo è:
+\begin{prototype}{syslog.h}
+{void syslog(int priority, const char *format, ...)}
+
+Genera un messaggio di priorità \param{priority}.
+
+\bodydesc{La funzione non restituisce nulla.}
+\end{prototype}
+
+Il comportamento della funzione è analogo quello di \func{printf}, e il valore
+dell'argomento \param{format} è identico a quello descritto nella pagina di
+manuale di quest'ultima (per i valori principali si può vedere la trattazione
+sommaria che se ne è fatto in \secref{sec:file_formatted_io}); l'unica
+differenza è che la sequenza \cmd{\%m} viene rimpiazzata dalla stringa
+restituita da \code{strerror(errno)}. Gli argomenti seguenti i primi due
+devono essere forniti secondo quanto richiesto da \func{format}.
+
+L'argomento \param{priority} permette invece di impostare l'importanza del
+messaggio; il valore deve essere impostato i valori possibili sono riportati
+in \secref{tab:sess_syslog_priority}.
+
+\begin{table}[htb]
+\centering
+\begin{tabular}[c]{|l|p{8cm}|}
+\hline
+\textbf{Valore}& \textbf{Significato}\\
+\hline
+\hline
+\macro{LOG\_EMERG}   & Il sistema è inutilizzabile. \\
+\macro{LOG\_ALERT}   & C'è una emergenza che richiede intervento immediato.\\
+\macro{LOG\_CRIT}    & Si è in una condizione critica.\\
+\macro{LOG\_ERR}     & Si è in una condizione di errore.\\
+\macro{LOG\_WARNING} & Messaggio di avvertimento.\\
+\macro{LOG\_NOTICE}  & Notizia significativa relativa al comportamento.\\
+\macro{LOG\_INFO}    & Messaggio informativo. \\
+\macro{LOG\_DEBUG}   & Messaggio di debug.\\
+\hline
+\end{tabular}
+\caption{Valori possibili per l'argomento \param{priority} di \func{syslog}.}
+\label{tab:sess_syslog_priority}
+\end{table}
+
+Dato che in molti programmi 
+
+Il sistema del \textit{syslog} usa la priorità del messaggio per classificare
+gli stessi, è inoltre possibile restringere l'emissione dei messaggi
+attraverso l'uso della funzione \func{setlogmask}, il cui prototipo è:
+\begin{prototype}{syslog.h}
+{int setlogmask(int mask)}
+
+Imposta la maschera dei log al valore specificato.
+
+\bodydesc{La funzione restituisce il precedente valore.}
+\end{prototype}