Exploiter des fichiers de logs

[Durée : 40 minutes]

Si vous avez à administrer un serveur, vous aurez souvent à examiner des fichiers de logs. Au delà d'outils de stats web qu'il peut aussi être intéressant d'installer, pouvoir créer des traitements à la demande sur ces données depuis la ligne de commande est souvent bien plus pratique que de rechercher les données dans un éditeur de texte.

La NASA (National Aeronautics and Space Administration) nous offre 2 mois de fichiers de logs de son serveur web, c'est à dire que chaque fois qu'un visiteur consulte une page ou indirectement charge une image ou un autre fichier sur une page, ces accès sont enregistrés. Nous allons chercher à savoir d’où viennent les accès, et combien de requêtes ont eu lieu chaque jour.

Utilisez la commande wget pour récupérer les fichiers de logs :

1
wget https://ics.utc.fr/libre/api-init/logs-example/NASA_access_log_Jul95.gz
2
wget https://ics.utc.fr/libre/api-init/logs-example/NASA_access_log_Aug95.gz

Si la commande wget n'est pas installée, installez là en premier lieu :

1
sudo apt install wget

Explications sur le format du fichier :

The logs are an ASCII file with one line per request, with the following columns:

  1. host making the request. A hostname when possible, otherwise the Internet address if the name could not be looked up.

  2. timestamp in the format "DAY MON DD HH:MM:SS YYYY", where DAY is the day of the week, MON is the name of the month, DD is the day of the month, HH:MM:SS is the time of day using a 24-hour clock, and YYYY is the year. The timezone is -0400.

  3. request given in quotes.

  4. HTTP reply code.

  5. bytes in the reply.

Question

Décompressez les 2 fichiers

Indice

Ces fichiers sont de type .gz. Lancez une recherche sur internet pour savoir comment décompresser ce type de fichier, par exemple avec les mots clés : décompresser .gz linux ou en anglais : uncompress .gz linux. Vous trouverez beaucoup de réponse, attention, certaines ne s'appliquent que aux fichiers ".tar.gz" (archives multi-fichiers) et non juste aux fichiers ".gz" (un seul fichier compressé), ce n'est pas ce dont nous avons besoin.

Solution

1
gunzip NASA_access_log_Aug95.gz
2
gunzip NASA_access_log_Jul95.gz

(gzip -d fonctionne aussi)

Question

Regroupez le contenu des 2 fichiers dans un seul fichier que vous nommerez "nasa.log", c'est à dire ajoutez les lignes du fichier du mois d'août à la suite des lignes du fichier du mois de juillet.

Solution

"cat NASA_access_log_Aug95" permet d'envoyer en sortie toutes le contenu du fichier d'août. Mais plutôt que de l'afficher, la redirection >> permet d'écrire cette sortie à la fin du fichier NASA_access_log_Jul95.log.

1
cat NASA_access_log_Aug95 >> NASA_access_log_Jul95
2
mv NASA_access_log_Jul95 nasa.log

Ensuite, vous pouvez faire le ménage :

1
mv NASA_access_log_Jul95 nasa.log
2
rm NASA_access_log_Aug95

Question

Vérifiez que vous ayez 3461612 lignes dans ce fichier. Quelle est la taille de ce fichier en Mo ?

Solution

1
wc -l nasa.log
2
ls -lh nasa.log

En résultat :

1
...$ wc -l nasa.log
2
3461612 nasa.log
3
...$ ls -lh nasa.log
4
-rw-rw-r-- 1 ics ics 356M janv.  7 11:54 nasa.log

Question

Le fichier est très gros. Quelle commande pouvez vous utiliser pour afficher son contenu sans saturer votre terminal avec toutes les données d'un coup ?

Solution

1
less nasa.log

Vous pouvez également utiliser d'autres outils, mais vu la taille du fichier certains éditeurs de texte peuvent avoir du mal.

Question

Nous allons nous intéresser aux requêtes qui concernent une page précise du site, la page /shuttle/countdown/ qui annonçait le temps restant avant le lancement de la prochaine fusée. En utilisant la commande grep, créez un fichier "countdown.log" qui ne contient que les lignes qui font référence à cette page. Vérifiez que vous obtenez bien 64 696 lignes.

Indice

Pour ne pas prendre d'autres pages, mettez l'adresse de la page entre guillemet, en rajoutant un espace avant et après, comme ceci : " /shuttle/countdown/ ".

Faites une recherche sur internet pour savoir rediriger la sortie d'une commande linux vers un fichier.

Solution

La commande grep prend 2 arguments.

1
grep ' /shuttle/countdown/ ' nasa.log > countdown.log

Question

[Question bonus] Vous venez de faire une recherche dans un fichier de 3 millions de lignes, et extrait 64 696 lignes de ce fichier. Trouvez une commande qui permette de mesurer combien le temps d'exécution d'une autre commande, et déterminer combien de temps cette opération a pris.

Indice

Cherchez sur internet "temps d'exécution d'une commande linux".

Solution

1
time grep ' /shuttle/countdown/ ' nasa.log > countdown.log

Qui donne en résultat sur un PC rapide :

1
real	0m0,143s
2
user	0m0,084s
3
sys	0m0,060s

Le premier chiffre est le plus intéressant d'un point de vu utilisateur : c'est le temps d'exécution réel entre le début et la fin de la commande.

Le 2eme est le temps de traitement "utilisateur", le temps consommé directement par le programme, dans ce cas c'est principalement le temps de l’opération de filtrage.

Le 3eme est le temps "système", le temps consommé par ce que le programme a demandé au noyau Linux, par exemple, les accès disques ou les allocations mémoires.

Question

Pour faire des stats sur les noms de domaines et adresses IP de provenance, on va éliminer les autres informations lors du traitement du fichier. Le nom de domaine (ou l'adresse IP) de provenance des visiteurs est en première position sur chaque ligne, suivi d'un caractère espace .

Dans une même ligne de commande, en partant du fichier countdown.log, combinez l'utilisation de 2 programmes :

  • Utilisez la commande cut traiter ce contenu et ne garder que la première colonne du fichier. Il faudra trouver les bons arguments à cette commande.

  • Utilisez la commande less pour afficher les résultats sans surcharger de données votre terminal

Indice

Utilisez un moteur de recherche, par exemple avec les mots clés : cut only first column shell. Aidez vous de la page man de la commande cut ("man cut")pour comprendre par vous même arguments des exemples proposés sur internet.

Ensuite, pour apprendre à combiner les deux commandes, consultez le chapitre "pipelines" du guide "LinuxCommand.org".

Solution

1
cut -f 1 -d ' ' countdown.log | less

On prend le premier champ (-f 1) avec le délimiteur de champ "espace" (-d ' ')

Question

Maintenant, on souhaite compter combien chaque nom de domaine ou adresse IP a réalisé d'accès.

Pour cela , on va partir de la commande précédente, mais avant d'afficher les résultats on va rajouter 2 opérations :

  • On va trier la liste, avec la commande "sort"

  • On va fusionner les lignes dupliquées, et compter le nombre de lignes dupliqué avec la commande "uniq" et le bon argument

Indice

Utilisez la page man de la commande uniq pour trouver l'argument qui permet de compter les lignes dupliquées (et donc le nombre d’occurrences d'une adresse).

Ensuite, combinez bien dans le bon ordre la commande de la question précédente, et les 2 nouveaux traitements ici, en enchainant plusieurs |, dans le bon ordre.

Solution

1
cut -f 1 -d ' ' countdown.log | sort | uniq -c | less

Les commandes sort et uniq sont très souvent utilisées ensembles.

Comme uniq ne fonctionne que sur les lignes adjacentes, si on trie les données au préalable, nous sommes sûr que toutes les lignes dupliquées sont adjacentes.

Question

À partir du résultat précédent, pouvez vous trouver les 10 adresses ou domaines qui ont fait le plus d'accès à la page countdown du site de la NASA sur la période étudiée ?

Indice

Les résultats de la commande précédente sont dans le désordre, connaissez vous une commande qui puisse remédier à cela ? Enchaînez là avec une nouvelle pipe après la commande uniq. Utilisez les bons arguments afin de vous assurer que le trie fonctionne bien.

Ensuite, enchaînez une nouvelle commande pour que seul les 10 premières lignes de la sortie soient affichées.

Solution

Vérifiez bien que vous ayez utilisé les 2 options du dernier sort, pour avoir le trie par ordre numérique, et décroissant.

1
cut -f 1 -d ' ' countdown.log | sort | uniq -c | sort -rn | head

En résultat :

1
    586 piweba3y.prodigy.com
2
    516 piweba4y.prodigy.com
3
    434 piweba1y.prodigy.com
4
    238 disarray.demon.co.uk
5
    223 piweba2y.prodigy.com
6
    214 alyssa.prodigy.com
7
    179 news.ti.com
8
    142 www-d1.proxy.aol.com
9
    140 derec
10
    137 163.206.137.21
Complément

Si vous êtes curieux de savoir d’où provient les résultats en tête du classement, vous pouvez aller voir le site prodigy.com tel qu'il existait en 1996.

Apparemment, il s'agit d'un fournisseur d'accès de l'époque.

Celui-ci permet de vous connecter à internet en utilisant votre PC avec un processeur 486, 8Mo de mémoire vive, et un modem 14.4 Kbps (soit de l'ordre de 1000 fois moins puissant que le matériel d'aujourd'hui selon tous les critères).

Question

[Question bonus] Jour par jour, combien y'a t'il eu d'accès à la page countdown ? En regardant cette liste, arrivez vous à repérer des jours ou il n'y a eu aucun accès ?

Indice

Identifiez le format de date utilisé dans countdown.log, par exemple [01/Jul/1995:00:07:37 -0400]. Commencez par ne garder que ce qui est après le premier "[". Puis ce qui n'est qu'avant le premier ":". Vous pouvez faire cela avec cut, même s'il existe aussi d'autres outils.

Solution

Les 2 premiers "cut" permettent de n'avoir que les dates. Ensuite, on peut appliquer "uniq" car les logs sont enregistrés chronologiquement et donc déjà triés.

1
cut -f 2 -d '[' countdown.log | cut -f 1 -d ':' | uniq -c | less

En résultat :

1
   2653 01/Jul/1995
2
   2283 02/Jul/1995
3
   3534 03/Jul/1995
4
   2583 04/Jul/1995
5
   3582 05/Jul/1995
6
   3469 06/Jul/1995
7
   2306 07/Jul/1995
8
    570 08/Jul/1995
9
    446 09/Jul/1995
10
   1125 10/Jul/1995
11
   1239 11/Jul/1995
12
   1511 12/Jul/1995
13
   3119 13/Jul/1995
14
   1634 14/Jul/1995
15
    879 15/Jul/1995
16
    878 16/Jul/1995
17
   1057 17/Jul/1995
18
    874 18/Jul/1995
19
    969 19/Jul/1995
20
    863 20/Jul/1995
21
    974 21/Jul/1995
22
    561 22/Jul/1995
23
    457 23/Jul/1995
24
    620 24/Jul/1995
25
    571 25/Jul/1995
26
    559 26/Jul/1995
27
    624 27/Jul/1995
28
    311 28/Jul/1995
29
    341 01/Aug/1995
30
    604 03/Aug/1995
31
    805 04/Aug/1995
32
    496 05/Aug/1995
33
    464 06/Aug/1995
34
    833 07/Aug/1995
35
    823 08/Aug/1995
36
    887 09/Aug/1995
37
    905 10/Aug/1995
38
    894 11/Aug/1995
39
    807 12/Aug/1995
40
    735 13/Aug/1995
41
    969 14/Aug/1995
42
    868 15/Aug/1995
43
    818 16/Aug/1995
44
    886 17/Aug/1995
45
    837 18/Aug/1995
46
    520 19/Aug/1995
47
    500 20/Aug/1995
48
    852 21/Aug/1995
49
    896 22/Aug/1995
50
    888 23/Aug/1995
51
    751 24/Aug/1995
52
    846 25/Aug/1995
53
    492 26/Aug/1995
54
    483 27/Aug/1995
55
    857 28/Aug/1995
56
   1095 29/Aug/1995
57
   1423 30/Aug/1995
58
   1870 31/Aug/1995
59

En regardant la liste, on peut s’apercevoir qu'il n'y manque quelques dates : les 29, 30, 31 juillets et le 2 août.

Complément

Consultez The Internet Traffic Archive (ou une page miroir si le site est indisponible) pour découvrir ce qui est à l'origine des jours d'interruption du serveur !

Les logs utilisés pour cette exercice ont été fournies par ce site.