Parser ses logs avec ‘awk’

couteau
Dernière mise a jour 20 Mar 2024 a 07:34 am

Le boulot de l’administrateur système c’est de gérer, d’analyser les évènements applicatifs, matériels ou réseaux conscrits dans des journaux appelés logs.
Lire des logs peut s’avérer fastidieux dès lors qu’on cherche une information précise. Heureusement, des commandes existent telles que « awk » et permettent de trier et parser les lignes pour les afficher de manière plus lisibles pour l’oeil humain.

« awk » le couteau suisse

« Awk » existe sous environnement unix depuis 1977. c’est un langage de programmation à part entière.
Il permet de faire des tas de choses, à tel point que pour un « adminsys » il est un allié indispensable.
Ah au fait, pas besoin d’installer de package , il fait partie du système.

le coeur du programme :

awk conditions(s) { instructions }…conditions(s) { instructions }

Avant le coeur du programme , possibilité d’effectuer des traitements préalables:

BEGIN { instructions }

Après le coeur du programme, idem

END { instructions }

Awk travaille sur chaque ligne. Il découpe les lignes en champs.
Chaque champ est récupéré dans une variable.
Par défaut le séparateur est "l'espace" mais il est possible d'en spécifier un différent.

Exemple 1

Pour comprendre plus vite ci-dessous un petite exemple :
Extrait d’une ligne d’un log apache /var/log/httpd/access_log:
192.168.0.24 - - [10/Mar/2017:08:21:19 +0100] "GET /grr/week_all.php?year=2016&month=02&day=13&area=1 HTTP/1.1"

Voici à quelles variables correspondent les champs.

$1 = 192.168.0.24
$2= –
$3 = –
$4 = [10/Mar/2017:08:21:19 +0100]
$5 = « GET /grr/week_all.php?year=2016&month=02&day=13&area=1 HTTP/1.1 »

Du coup si on veut récupérer une liste d’IP :
cat /var/log/httpd/access_log |awk '{print $1 }'
une liste d’ip et la date:
cat /var/log/httpd/access_log |awk '{print $1" "$4 }'

Exemple 2

Dernier exemple plus compliqué , histoire de montrer toute la puissance du bouzin.
A partir du fichier /etc/passwd , nous allons extraire le nombre d’utilisateurs unix , ceux qui possèdent un répertoire « home ».
Pour se représenter le formatage de la ligne, voici un extrait d’une ligne du fichier:

admin:x:1021:1000::/home/admin:/bin/bash
puppet:x:52:52:Puppet:/var/lib/puppet:/sbin/nologin

Pour trouver le nombre d’utilisateurs qui ont le chemin /home/ dans /etc/passwd :

awk 'BEGIN { FS=":";c=0 } $6~/home/{ c++ } END{print c}' /etc/passwd

BEGIN =>traitement avant exécution du coeur de programme

{ FS= »: »;c=0 } => bloc d’instructions.

FS => variable prédéfinie « File Separator » , précise le délimiteur qui sera ici « : »

c=0 => initialisation d’une variable compteur à 0

$6~/home/=> condition , si le champ $6 match avec l’expression « /home » …

{ c++ } => alors on incrémente de 1 la variable compteur (bloc d’instruction qui suit la condition)

END{print c} => affiche le contenu de la variable compteur , à savoir le nombre de fois ou elle a rencontré un « /home »

Récupération et affichage des infos principales

Revenons à l’analyse de nos logs. je vais travailler avec le log apache sur une centos , c’est à dire le fichier:

/var/log/httpd/access_log

Mais vous pouvez très bien le faire aussi sur un log nginx, fail2ban etc…en changeant les chemins bien sûr 😉

  • Afficher toutes les lignes sauf celles qui contiennent mon @IP:

awk '!/xx.xx.xx.xx/' /var/log/httpd/access_log

  • URL les plus populaires:

cat /var/log/httpd/access_log | awk '{ print $7 }' | sort | uniq -c | sort -rn | head -n 25

  • Afficher les IP clientes qui ont consultées les pages:

cat /var/log/httpd/access_log|grep HTTP/1.1\"\ 200|awk '{print $1" "$2" "$4 }'|sort -n|uniq

cat /var/log/httpd/access_log |grep HTTP/1.1\"\ 200 | awk '{print $1" "$2" "$4 }'|sed s'/\(:[0-9]\{2\}\)\{3\}//' | sort -n|uniq

  • Connaitre la provenance des Ip des visiteurs :

apt-get install geoip-bin

geoiplookup 207.xx.xx.xx

Identifier les problèmes sur son site:

Quand on demande une page au serveur web via notre navigateur, un code retour est renvoyé dans la réponse du serveur au navigateur pour savoir si la requête est acceptée ou si pour diverses raisons elle n’a pu aboutir.

200 - OK=> requête traitée avec succès
206 -Partial Content => une partie seulement de la ressource a été transmise
301- Moved Permanently => document déplacé de façon permanente
302- Found => document déplacé de façon temporaire
304 - Not Modified => Document non modifié depuis la dernière requête
401- Unauthorised => authentification nécessaire pour accéder à la ressource
403 - Forbidden=> les droits d'accès ne permettent pas au client d'accéder à la ressource
404 - Not Found => Ressource non trouvée. La bête noire des webmasters!
  • Pour n’afficher que les url qui renvoient des erreurs 404 :

awk '/404/' /var/log/httpd/access_log

  • Lister toutes les demandes d’accès aux ressources qui renvoient autre chose que « 200 » :

awk '($9 ~ /404/)' /var/log/httpd/access_log | awk '{print $9,$7}' | sort

  • Afficher les user-agent par popularité:

awk -F\" '{print $6}' /var/log/httpd/access_log | sort | uniq -c | sort -fr

Agréger les infos…

…et constituer un fichier de log:

exemple:
awk '/404/' /var/log/httpd/access_log >> fichier_404.log

Cela va récupérer et copier toutes les lignes erreurs 404 pour les mettre dans un fichier créé pour l’occasion: fichier_404.log

cat /var/log/nginx/access.log | awk '{ printf("%-15s\t%s\t%s\t%s\n", $1, $6, $9, $7) }'
Ici, on affiche proprement les infos les plus importantes concernant les ip clientes et les pages qu’elles ont consultées.

Conclusion:

La commande awk est bien pratique à condition de la maitriser un minimum. Impossible de montrer l’étendue complète de toutes ses possibilités mais j’espère que je vous aurai persuadé de l’utiliser à minima pour récupérer et formater des infos rapidement. Mais pour l’analyse de logs énormes de nombreux produits existent et font ça très bien.On peut citer notamment le très en vogue Piwik  Matomo.
Le but de ce tuto étant évidemment de montrer la puissance du awk et d’une de ses utilisations possibles.

2 commentaires sur Parser ses logs avec ‘awk’

Leave a Reply

Votre adresse de messagerie ne sera pas publiée.


*