Pour véritablement gérer un serveur web, il est nécessaire de disposer d'un retour d'informations à propos de l'activité et des performances du serveur, ainsi que de tout problème qui pourrait survenir. Le serveur HTTP Apache propose des fonctionnalités de journalisation souples et très complètes. Ce document décrit comment configurer ces fonctionnalités de journalisation et interpréter le contenu des journaux.
Le serveur HTTP Apache fournit toute une variété de mécanismes différents pour la journalisation de tout ce qui peut se passer au sein de votre serveur, depuis la requête initiale, en passant par le processus de mise en correspondance des URLs, et jusqu'à la fermeture de la connexion, y compris toute erreur pouvant survenir au cours du traitement. De plus, certains modules tiers fournissent des fonctionnalités de journalisation ou insèrent des entrées dans les fichiers journaux existants, et les applications comme les programmes CGI, les scripts PHP ou autres gestionnaires peuvent envoyer des messages vers le journal des erreurs du serveur.
Ce document décrit le fonctionnement des modules de journalisation fournis en standard avec le serveur httpd.
Tout utilisateur qui a les droits en écriture sur le répertoire dans lequel Apache httpd écrit ses journaux pourra quasi certainement avoir accès à l'uid sous lequel le serveur est démarré, en l'occurrence habituellement root. N'accordez PAS aux utilisateurs l'accès en écriture au répertoire dans lequel les journaux sont stockés sans savoir exactement quelles en seraient les conséquences ; voir le document conseils sur la sécurité pour plus de détails.
En outre, les journaux peuvent contenir des informations fournies directement par un client, sans caractères d'échappement. Des clients mal intentionnés peuvent donc insérer des caractères de contrôle dans les journaux, et il convient par conséquent d'être très prudent lors de la manipulation des journaux bruts.
Le journal des erreurs du serveur, dont le nom et la localisation sont
définis par la directive
Le journal des erreurs est habituellement enregistré dans un fichier
(en général error_log
sur les systèmes de type Unix et
error.log
sur Windows et OS/2). Sur les systèmes de type Unix,
le serveur peut aussi enregistrer ses erreurs dans
syslog
ou les
rediriger vers un programme par l'intermédiaire d'un
tube de communication (pipe).
Le format par défaut du journal des erreurs est descriptif et de forme relativement libre. Certaines informations apparaissent cependant dans la plupart des entrées du journal. Voici un message typique à titre d'exemple :
Le premier champ de l'entrée du journal est la date et l'heure du
message. Le second champ indique la sévérité de l'erreur rapportée. La
directive
Une grande variété de messages différents peuvent apparaître dans le
journal des erreurs. La plupart d'entre eux sont similaires à l'exemple
ci-dessus. Le journal des erreurs peut aussi contenir des informations de
débogage en provenance de scripts CGI. Toute information qu'un script CGI
écrit sur la sortie d'erreurs standard stderr
sera recopiée
telle quelle dans le journal des erreurs.
La directive %L
à la fois dans le journal des erreurs et
dans le
journal des accès, ce qui aura pour effet de générer un identifiant
d'entrée qui vous permettra de corréler les entrées du journal des
erreurs avec celles du journal des accès.
Pendant la phase de test, il est souvent utile de visualiser en continu le journal des erreurs afin de détecter tout problème éventuel. Sur les systèmes de type Unix, ceci s'effectue à l'aide de la commande :
La directive
Pour ce faire, vous devez spécifier le nom du module dans votre
directive
Dans cet exemple, le niveau de journalisation général est défini
à info, et à trace5
pour
RewriteLog
.Le journal des accès au serveur
enregistre toutes les requêtes que traite
ce dernier. La localisation et le contenu du journal des accès sont définis
par la directive
Bien évidemment, le stockage d'informations dans le journal des accès n'est que le point de départ de la gestion de la journalisation. L'étape suivante consiste à analyser ces informations de façon à pouvoir en extraire des statistiques utiles. L'analyse de journaux en général est en dehors du sujet de ce document et ne fait pas vraiment partie intégrante du travail du serveur web lui-même. Pour plus d'informations à propos de ce sujet et des applications dédiées à l'analyse de journaux, vous pouvez vous référer à Open Directory ou Yahoo.
Différentes versions du démon Apache httpd utilisaient d'autres modules
et directives pour contrôler la journalisation des accès, à l'instar de
mod_log_referer, mod_log_agent, et de la directive
TransferLog
. La directive
Le format du journal des accès est hautement configurable. Il est
défini à l'aide d'une chaîne de format qui ressemble sensiblement à la
chaîne de format de style langage C de printf(1). Vous trouverez quelques
exemples dans les sections suivantes. Pour une liste exhaustive de ce que
peut contenir une chaîne de format, vous pouvez vous référer au chapitre
chaînes de format de la
documentation du module
Voici une configuration typique pour le journal des accès :
Ici est définie l'identité common
qui est
ensuite associée à une chaîne de format de journalisation particulière.
La chaîne de format est constituée de directives débutant par le
caractère %, chacune d'entre elles indiquant au serveur d'enregistrer
un élément particulier d'information. Des caractères littéraux peuvent
aussi être insérés dans la chaîne de format ; il seront copiés tels
quels dans le flux de sortie destiné à la journalisation.
Les guillemets ("
) doivent être échappées en les faisant
précéder d'un anti-slash (\
) afin qu'elles ne soient pas
interprétées comme la fin de la chaîne de format. La chaîne de format
peut aussi contenir les caractères de contrôle spéciaux
"\n
" et "\t
" pour insérer respectivement
un passage à la ligne et une tabulation.
La directive
La configuration ci-dessus va enregistrer les entrées de journalisation selon un format connu sous le nom de Common Log Format (CLF) pour "Format de journalisation standard". Ce format standard peut être produit par de nombreux serveurs web différents et lu par de nombreux programmes d'analyse de journaux. Les entrées de fichier journal générées selon le format CLF ressemblent à ceci :
Chaque partie de cette entrée de journal est décrite dans ce qui suit.
127.0.0.1
(%h
)On
, le serveur va essayer de déterminer le nom de l'hôte
et de l'enregistrer à la place de l'adresse IP. Cette configuration
n'est cependant pas recommandée car elle peut ralentir le serveur de
manière significative. Il est par conséquent préférable d'utiliser un
processeur d'analyse de journaux a posteriori
tel que -
(%l
)identd
sur la machine cliente. Cette information est
très peu fiable et ne devrait jamais être utilisée, sauf dans le cas
de réseaux internes étroitement contrôlés. Le démon httpd ne cherchera
d'ailleurs à obtenir cette information que si la directive
On
.frank
(%u
)REMOTE_USER
. Si le statut de la requête (voir plus loin)
est 401, cette identifiant n'est pas fiable car l'utilisateur n'est
pas encore authentifié. Si le document n'est pas protégé par
mot de passe, cette partie d'information sera représentée par
"-
", comme la partie précédente.[10/Oct/2000:13:55:36 -0700]
(%t
)
[jour/mois/année:heure:minutes:secondes zone]
jour = 2*chiffre
mois = 3*lettre
année = 4*chiffre
heure = 2*chiffre
minutes = 2*chiffre
secondes = 2*chiffre
zone = (`+' | `-') 4*chiffre
%{format}t
dans la chaîne de format du
journal, où format
est une chaîne de format
de la forme de celle de la fonction strftime(3)
de la bibliothèque C standard, ou choisie parmi les
formats spéciaux supportés. Pour plus de détails,
reportez-vous aux. chaînes de format
de "GET /apache_pb.gif HTTP/1.0"
(\"%r\"
)GET
. Ensuite, le
client a demandé la ressource /apache_pb.gif
, et enfin,
le client a utilisé le protocole HTTP/1.0
. Il est aussi
possible d'enregistrer séparément une ou plusieurs parties de la
requête. Par exemple, la chaîne de format "%m %U %q %H
"
va enregistrer la méthode, le chemin, la chaîne de la requête et le
protocole, ce qui donnera le même résultat que
"%r
".200
(%>s
)2326
(%b
)-
". Pour indiquer l'absence de contenu
par "0
", utilisez %B
au lieu de
%b
.Une autre chaîne de format couramment utilisée est le "Combined Log Format" (Format de journalisation combiné). Il s'utilise comme suit :
Ce format est identique au Common Log Format, avec deux champs
supplémentaires. Chacun de ces deux champs utilise la directive
commençant par le caractère "%" %{header}i
,
où header peut être n'importe quel en-tête de requête HTTP.
Avec ce format, le journal des accès se présentera comme suit :
Les champs supplémentaires sont :
"http://www.example.com/start.html"
(\"%{Referer}i\"
)/apache_pb.gif
ou
inclut ce dernier fichier)."Mozilla/4.08 [en] (Win98; I ;Nav)"
(\"%{User-agent}i\"
)Plusieurs journaux d'accès peuvent être créés en spécifiant tout
simplement plusieurs directives
ReferLog
et
AgentLog
.
Cet exemple montre aussi qu'il n'est pas obligatoire d'associer
une chaîne de format à un alias au moyen de la directive
Il est parfois souhaitable d'exclure certaines entrées des journaux
d'accès en fonction des caractéristiques de la requête du client. On
peut aisément accomplir ceci à l'aide des
variables d'environnement. Tout d'abord, une
variable d'environnement doit être définie pour indiquer que la
requête remplit certaines conditions. Pour ceci, on utilise en général
la directive env=
de la directive
Autre exemple, imaginons l'enregistrement des requêtes en provenance d'utilisateurs de langue anglaise dans un journal, et celles des autres utilisateurs dans un autre journal.
Dans le contexte d'une mise en cache, il peut être intéressant de connaître l'efficacité du cache. Pour y parvenir, on pourrait utiliser cette méthode simple :
-
, tandis que dans le cas contraire elle sera
1
.
En plus de la syntaxe env=
, la directive
Dans le premier exemple, le User-agent
sera
enregistré si le code d'état HTTP est 400 ou 501. Dans le cas
contraire, c'est un caractère "-" qui sera enregistré à la place.
Dans le second exemple, le Referer
sera enregistré si
le code d'état HTTP n'est pas 200, 204, ou 302
(remarquez le caractère "!" avant les codes d'état).
Bien que nous venions de montrer que la journalisation conditionnelle est souple et très puissante, cette méthode de contrôle du contenu des journaux n'est pas la seule. Les fichiers journaux sont plus utiles quand ils contiennent un enregistrement complet de l'activité du serveur, et il est souvent plus aisé de simplement traiter à posteriori les fichiers journaux pour supprimer les requêtes que vous ne voulez pas y voir apparaître.
Même dans le cas d'un serveur modérément sollicité, la quantité d'informations stockées dans les fichiers journaux est très importante. Le fichier journal des accès grossit en général d'1 Mo ou plus toutes les 10000 requêtes. Il est par conséquent nécessaire d'effectuer périodiquement la rotation des journaux en déplaçant ou supprimant les fichiers correspondants. On ne peut pas le faire pendant que le serveur est en cours d'exécution, car Apache httpd va continuer à écrire dans l'ancien fichier journal aussi longtemps qu'il le maintiendra ouvert. C'est pourquoi le serveur doit être redémarré après le déplacement ou la suppression des fichiers journaux de façon à ce qu'il en ouvre de nouveaux.
Avec un redémarrage graceful, on peut faire en sorte que le serveur ouvre de nouveaux fichiers journaux sans perdre de connexions existantes ou en cours avec les clients. Cependant, pour que ceci soit possible, le serveur doit continuer à écrire dans les anciens fichiers journaux pendant qu'il termine le traitement des requêtes en cours. Il est donc nécessaire d'attendre un certain temps après le rédémarrage avant d'effectuer tout traitement sur les fichiers journaux. Voici un scénario typique dans lequel on effectue une simple rotation des journaux en compressant les anciens fichiers correspondants afin de gagner de l'espace disque :
La section suivante présente une autre méthode de rotation des journaux qui consiste à utiliser les journaux redirigés.
Nous avons vu que le démon httpd écrivait les informations de
journalisation des erreurs et des accès dans un fichier journal ;
il peut aussi
rediriger ces informations vers un autre processus par l'intermédiaire d'un
tube de communication (pipe). Cette fonctionnalité améliore
considérablement la souplesse de la journalisation, sans ajouter de code
au serveur principal. Pour rediriger les informations de journalisation
vers un tube de communication, remplacez simplement le nom de fichier
journal par
le caractère pipe "|
", suivi du nom de l'exécutable qui va
recueillir les entrées de journal sur son entrée
standard. Le serveur va
lancer le processus de redirection des journaux au moment du démarrage du
serveur, et le relancera s'il cesse de fonctionner
pendant l'exécution du serveur.
(Nous dénommons cette technique "journalisation
redirigée fiable" grâce à cette dernière fonctionnalité.)
Les processus de journalisation redirigée sont lancés par le processus httpd parent, et héritent de l'UID de ce dernier. Cela signifie que les programmes de journalisation dirigée s'exécutent généralement en tant que root. Il est donc très important que ces programmes soient simples et sécurisés.
Un des grands avantages de la journalisation redirigée est la possibilité
d'effectuer la rotation des journaux sans avoir à redémarrer le serveur. Pour
accomplir cette tâche, le serveur HTTP Apache fournit un programme simple
appelé
Notez que l'ensemble de la commande qui sera appelée par le tube de communication a été placée entre guillemets. Bien que cet exemple concerne le journal des accès, la même technique peut être utilisée pour le journal des erreurs.
Il existe un autre programme de rotation des journaux similaire mais beaucoup plus souple : il s'agit de "cronolog", non fourni par Apache, mais disponible ici.
Comme la journalisation conditionnelle, la journalisation redirigée est un outil très puissant, mais si elle existe, il est préférable d'utiliser une solution plus simple comme le traitement à posteriori hors ligne.
Par défaut, le processus de redirection du journal est lancé sans
invoquer un shell. Pour invoquer un shell, utilisez "|$
"
au lieu de "|
" (en général avec /bin/sh -c
)
:
Il s'agissait du comportement par défaut sous Apache 2.2. Selon
les spécificités du shell, ceci peut générer un processus shell
supplémentaire pour toute la durée du programme de redirection du
journal, et induire des problèmes de gestion de signaux au cours du
redémarrage. La notation "||
" est aussi supportée pour
des raisons de compatibilité avec Apache 2.2 et est équivalente à
"|
".
Lorsqu'un serveur possède plusieurs hôtes virtuels, il existe de nombreuses solutions pour gérer
les fichiers journaux. Par exemple, on peut utiliser les journaux comme
s'il s'agissait d'un serveur avec un seul hôte. Il suffit pour cela de
placer les directives de journalisation en dehors des sections
Si des directives
Il existe un très bon compromis pour le journal des accès. En intégrant les informations à propos de l'hôte virtuel à la chaîne de format du journal, il est possible de journaliser tous les hôtes dans le même journal, puis de séparer ultérieurement le journal en plusieurs journaux individuels. Considérons par exemple les directives suivantes :
Le champ %v
sert à enregistrer le nom de l'hôte virtuel qui
traite la requête. Un programme tel que split-logfile peut ensuite être utilisé
pour générer "à froid" autant de journaux que d'hôtes virtuels.
Le module
Le module
Au démarrage, le démon httpd Apache enregistre l'identifiant du
processus httpd parent dans le fichier logs/httpd.pid
.
Le nom de ce fichier peut être modifié à l'aide de la directive
Afin de faciliter le débogage, la directive