Introduction
Bienvenue dans l'univers du traitement de texte avec AWK. Dans ce laboratoire, vous apprendrez à utiliser la commande awk pour analyser des fichiers journaux (logs), une tâche courante pour les administrateurs système et les analystes de données. AWK est un outil puissant pour traiter des données textuelles structurées sous Linux, vous permettant d'extraire, de filtrer et de transformer des informations de manière efficace.
Imaginez que vous soyez un administrateur système junior chargé d'analyser les journaux d'un serveur pour identifier des menaces de sécurité potentielles et des problèmes de performance. La commande awk sera votre outil principal pour cette mission, vous permettant de parcourir rapidement de gros fichiers journaux et d'en extraire des informations pertinentes.
Examen du fichier journal
Commençons par examiner le contenu de notre fichier journal d'exemple. Ce fichier contient des journaux d'accès serveur simulés que nous analyserons tout au long de ce laboratoire.
Tout d'abord, accédez au répertoire du projet :
cd ~/project
Maintenant, affichons les premières lignes du fichier journal :
head -n 5 server_logs.txt
Vous devriez obtenir un résultat similaire à celui-ci :
2023-08-01 08:15:23 192.168.1.100 GET /index.html 200
2023-08-01 08:16:45 192.168.1.101 GET /about.html 200
2023-08-01 08:17:30 192.168.1.102 POST /login.php 302
2023-08-01 08:18:12 192.168.1.103 GET /products.html 404
2023-08-01 08:19:05 192.168.1.104 GET /services.html 200
Ce fichier journal contient des informations sur les requêtes serveur, notamment la date et l'heure, l'adresse IP, la méthode HTTP, la ressource demandée et le code d'état.
Utilisation de base d'AWK - Affichage de champs spécifiques
Maintenant que nous connaissons la structure de notre fichier journal, utilisons AWK pour extraire des informations spécifiques. Par défaut, AWK divise chaque ligne en champs basés sur les espaces. Nous pouvons faire référence à ces champs en utilisant $1, $2, etc., où $1 est le premier champ, $2 le deuxième, et ainsi de suite.
Extrayons les adresses IP (le troisième champ) de notre fichier journal :
awk '{print $3}' server_logs.txt | head -n 5
Vous devriez voir un résultat similaire à celui-ci :
192.168.1.100
192.168.1.101
192.168.1.102
192.168.1.103
192.168.1.104
Dans cette commande :
awk '{print $3}'indique à AWK d'imprimer le troisième champ de chaque ligne.- Nous utilisons un tube (
|) pour envoyer la sortie vershead -n 5afin de limiter l'affichage aux 5 premières lignes.
Maintenant, affichons à la fois l'adresse IP et la ressource demandée :
awk '{print $3, $5}' server_logs.txt | head -n 5
Résultat :
192.168.1.100 /index.html
192.168.1.101 /about.html
192.168.1.102 /login.php
192.168.1.103 /products.html
192.168.1.104 /services.html
Ici, nous imprimons le troisième champ (adresse IP) et le cinquième champ (ressource demandée) pour chaque ligne.
Filtrage des entrées de journal
L'une des forces d'AWK est sa capacité à filtrer les données en fonction de conditions. Utilisons cette fonctionnalité pour trouver toutes les requêtes POST dans notre fichier journal, car elles pourraient être plus sensibles en termes de sécurité que les requêtes GET.
Exécutez la commande suivante :
awk '$4 == "POST" {print $0}' server_logs.txt
Cette commande peut imprimer des centaines de lignes car le fichier d'exemple contient 5 000 entrées. Si vous souhaitez simplement inspecter un échantillon gérable pendant votre apprentissage, ajoutez | head -n 10 :
awk '$4 == "POST" {print $0}' server_logs.txt | head -n 10
La vérification accepte également la commande awk simple, utilisez donc la version qui vous permet de lire le résultat le plus confortablement.
Analysons la syntaxe de cette commande pour comprendre comment fonctionne le filtrage AWK :
$4 == "POST"- Il s'agit d'un motif ou d'une condition qu'AWK évalue pour chaque ligne :$4fait référence au quatrième champ de la ligne actuelle (dans notre fichier journal, il s'agit de la méthode HTTP)==est l'opérateur d'égalité qui vérifie si deux valeurs sont identiques"POST"est la chaîne de caractères avec laquelle nous comparons
{print $0}- Il s'agit de l'action qu'AWK effectue lorsque la condition est vraie :- Les accolades
{}entourent l'action printest la commande pour afficher du texte$0représente la ligne entière actuelle (tous les champs)
- Les accolades
La structure de la commande suit le modèle AWK : condition {action}. AWK lit chaque ligne, et si la condition est évaluée comme vraie, il exécute l'action. Si aucune condition n'est spécifiée (comme dans nos exemples précédents), l'action est effectuée pour chaque ligne.
Vous devriez obtenir un résultat similaire à celui-ci :
2023-08-01 08:17:30 192.168.1.102 POST /login.php 302
2023-08-01 09:23:45 192.168.1.110 POST /submit_form.php 200
2023-08-01 10:45:12 192.168.1.115 POST /upload.php 500
Maintenant, trouvons toutes les requêtes ayant abouti à un code d'état 404 (Non trouvé) :
awk '$6 == "404" {print $1, $2, $5}' server_logs.txt
Cette commande suit le même modèle mais avec des valeurs différentes :
- La condition
$6 == "404"vérifie si le sixième champ (code d'état) est égal à 404 - L'action
{print $1, $2, $5}n'imprime que des champs spécifiques :$1- Premier champ (date)$2- Deuxième champ (heure)$5- Cinquième champ (ressource demandée)
Cette impression sélective vous permet de vous concentrer uniquement sur les informations dont vous avez besoin.
Résultat :
2023-08-01 08:18:12 /products.html
2023-08-01 09:30:18 /nonexistent.html
2023-08-01 11:05:30 /missing_page.html
Vous pouvez combiner plusieurs conditions en utilisant des opérateurs logiques :
&&pour ET (les deux conditions doivent être vraies)||pour OU (au moins une condition doit être vraie)!pour NON (négation d'une condition)
Par exemple, pour trouver toutes les requêtes POST ayant abouti à une erreur (code d'état >= 400) :
awk '$4 == "POST" && $6 >= 400 {print $0}' server_logs.txt
Ces filtres peuvent vous aider à identifier rapidement des problèmes potentiels ou des activités suspectes dans vos journaux serveur.
Comptage et synthèse des données
AWK est excellent pour compter les occurrences et synthétiser des données. Utilisons-le pour compter le nombre de requêtes pour chaque code d'état HTTP.
Exécutez cette commande :
awk '{count[$6]++} END {for (code in count) print code, count[code]}' server_logs.txt | sort -n
Cette commande est plus complexe, décomposons-la étape par étape :
{count[$6]++}- Il s'agit de l'action principale effectuée pour chaque ligne :countest un tableau (tableau associatif ou dictionnaire) que nous créons[$6]utilise la valeur du 6ème champ (code d'état) comme index/clé du tableau++est l'opérateur d'incrémentation, ajoutant 1 à la valeur actuelle- Ainsi, pour chaque ligne, nous incrémentons le compteur pour le code d'état spécifique trouvé
END {for (code in count) print code, count[code]}- Ceci est exécuté après le traitement de toutes les lignes :ENDest un motif spécial qui correspond à la fin de l'entrée{...}contient l'action à effectuer une fois que toute l'entrée a été traitéefor (code in count)est une boucle qui parcourt toutes les clés du tableaucountprint code, count[code]imprime chaque code d'état et son nombre d'occurrences
| sort -n- Envoie la sortie vers la commandesort, qui trie numériquement
Lorsqu'AWK traite un tableau comme count[$6]++, il effectue automatiquement les opérations suivantes :
- Crée le tableau s'il n'existe pas
- Crée un nouvel élément avec la valeur 0 si la clé n'existe pas
- Puis incrémente la valeur de 1
Vous devriez obtenir un résultat similaire à celui-ci :
200 3562
301 45
302 78
304 112
400 23
403 8
404 89
500 15
Ce résumé vous montre rapidement la répartition des codes d'état dans votre fichier journal.
Maintenant, trouvons les 5 ressources les plus fréquemment consultées :
awk '{count[$5]++} END {for (resource in count) print count[resource], resource}' server_logs.txt | sort -rn | head -n 5
Cette commande suit un modèle similaire avec quelques changements :
{count[$5]++}- Compte les occurrences du 5ème champ (la ressource demandée)END {for (resource in count) print count[resource], resource}- Après le traitement de toutes les lignes :- Imprime le nombre d'abord, suivi de la ressource
- Ce changement d'ordre facilite le tri numérique par nombre
| sort -rn- Trie numériquement dans l'ordre inverse (les nombres les plus élevés en premier)| head -n 5- Limite la sortie aux 5 premières lignes (top 5 des résultats)
Résultat :
1823 /index.html
956 /about.html
743 /products.html
512 /services.html
298 /contact.html
Ces commandes AWK démontrent la puissance de l'utilisation des tableaux pour le comptage et la synthèse. Vous pouvez adapter ce modèle pour compter n'importe quel champ ou combinaison de champs dans vos données.
Par exemple, pour compter le nombre de requêtes par adresse IP :
awk '{count[$3]++} END {for (ip in count) print ip, count[ip]}' server_logs.txt
Pour compter les requêtes à la fois par méthode et par état :
awk '{key=$4"-"$6; count[key]++} END {for (k in count) print k, count[k]}' server_logs.txt
Ces résumés peuvent vous aider à comprendre les modèles de trafic et à identifier les ressources populaires (ou problématiques) sur votre serveur.
Création d'un rapport simple
Pour notre dernière tâche, créons un rapport HTML simple résumant quelques informations clés de notre fichier journal. Nous utiliserons un script AWK stocké dans un fichier séparé pour cette opération plus complexe.
Cette étape combine plusieurs idées AWK abordées dans les sections précédentes :
- des compteurs tels que
total++ - des tableaux tels que
ip_count[$3]++ - un bloc
ENDqui imprime le résumé final
Si le script semble long au premier abord, concentrez-vous sur un bloc à la fois. Vous n'avez pas besoin de mémoriser tout le fichier avant de l'exécuter.
Tout d'abord, créez un fichier nommé log_report.awk avec le contenu suivant :
Conseils : Copiez le contenu ci-dessous et collez-le dans votre terminal pour créer le fichier.
cat << 'EOF' > log_report.awk
BEGIN {
print "<html><body>"
print "<h1>Server Log Summary</h1>"
total = 0
errors = 0
}
{
total++
if ($6 >= 400) errors++
ip_count[$3]++
resource_count[$5]++
}
END {
print "<p>Total requests: " total "</p>"
print "<p>Error rate: " (errors/total) * 100 "%</p>"
print "<h2>Top 5 IP Addresses</h2>"
print "<ul>"
for (ip in ip_count) {
top_ips[ip] = ip_count[ip]
}
n = asort(top_ips, sorted_ips, "@val_num_desc")
for (i = 1; i <= 5 && i <= n; i++) {
for (ip in ip_count) {
if (ip_count[ip] == sorted_ips[i]) {
print "<li>" ip ": " ip_count[ip] " requests</li>"
delete ip_count[ip]
break
}
}
}
print "</ul>"
print "<h2>Top 5 Requested Resources</h2>"
print "<ul>"
for (resource in resource_count) {
top_resources[resource] = resource_count[resource]
}
n = asort(top_resources, sorted_resources, "@val_num_desc")
for (i = 1; i <= 5 && i <= n; i++) {
for (resource in resource_count) {
if (resource_count[resource] == sorted_resources[i]) {
print "<li>" resource ": " resource_count[resource] " requests</li>"
delete resource_count[resource]
break
}
}
}
print "</ul>"
print "</body></html>"
}
EOF
Comprenons ce script AWK section par section :
Bloc BEGIN : S'exécute avant de traiter toute ligne d'entrée
BEGIN { print "<html><body>" ## Début de la structure HTML print "<h1>Server Log Summary</h1>" total = 0 ## Initialiser le compteur pour le total des requêtes errors = 0 ## Initialiser le compteur pour les requêtes en erreur }Bloc de traitement principal : S'exécute pour chaque ligne du fichier d'entrée
{ total++ ## Incrémenter le compteur total de requêtes if ($6 >= 400) errors++ ## Compter les réponses d'erreur (codes d'état >= 400) ip_count[$3]++ ## Compter les requêtes par adresse IP (champ 3) resource_count[$5]++ ## Compter les requêtes par ressource (champ 5) }Bloc END : S'exécute après le traitement de toutes les lignes d'entrée
END { ## Imprimer les statistiques récapitulatives print "<p>Total requests: " total "</p>" print "<p>Error rate: " (errors/total) * 100 "%</p>" ## Traiter et imprimer les 5 meilleures adresses IP ## ... ## Traiter et imprimer les 5 meilleures ressources demandées ## ... print "</body></html>" ## Fin de la structure HTML }
Avant de continuer, notez le flux global :
BEGINimprime les balises HTML d'ouverture et initialise les compteurs.- Le bloc central traite chaque ligne de journal et met à jour les totaux.
ENDimprime le rapport final après l'analyse de chaque ligne.
Examinons la logique de tri pour les meilleures IP (la section des ressources fonctionne de la même manière) :
## Copier les comptes dans un nouveau tableau pour le tri
for (ip in ip_count) {
top_ips[ip] = ip_count[ip]
}
## Trier le tableau par valeur dans l'ordre décroissant
n = asort(top_ips, sorted_ips, "@val_num_desc")
## Imprimer les 5 meilleures entrées
for (i = 1; i <= 5 && i <= n; i++) {
## Trouver l'IP originale qui correspond à ce compte
for (ip in ip_count) {
if (ip_count[ip] == sorted_ips[i]) {
print "<li>" ip ": " ip_count[ip] " requests</li>"
delete ip_count[ip]
break
}
}
}
Dans ce script :
- La fonction
asort()trie le tableau "@val_num_desc"est un argument spécial qui lui indique de trier numériquement par valeur dans l'ordre décroissant- Les boucles imbriquées trouvent et impriment les 5 meilleures entrées
Vous pouvez concevoir les boucles imbriquées comme suit :
- la première boucle décide quels comptes appartiennent au top 5
- la deuxième boucle trouve quelle adresse IP ou ressource a produit chaque compte
- après avoir imprimé une correspondance, le script supprime cette clé afin que des comptes égaux ne dupliquent pas la même entrée
Ce modèle de recherche est plus avancé que les étapes précédentes, il est donc normal que ce soit la première partie du laboratoire qui ressemble à de la vraie programmation plutôt qu'à une commande d'une ligne.
Maintenant, exécutons notre script AWK pour générer le rapport :
awk -f log_report.awk server_logs.txt > log_report.html
L'option -f indique à AWK de lire le script à partir du fichier spécifié :
-f log_report.awk- Lit le script AWK depuis le fichierlog_report.awkserver_logs.txt- Traite ce fichier en utilisant le script> log_report.html- Redirige la sortie vers le fichierlog_report.html
Vous pouvez afficher le contenu du rapport en utilisant la commande cat :
cat log_report.html
Si la sortie HTML semble difficile à parcourir dans le terminal, prévisualisez d'abord uniquement la première partie :
head -n 15 log_report.html
Ce rapport fournit un résumé du total des requêtes, du taux d'erreur, des 5 meilleures adresses IP et des 5 meilleures ressources demandées. Dans un scénario réel, vous pourriez ouvrir ce fichier HTML dans un navigateur web pour une vue formatée.
L'approche que nous avons utilisée dans ce script démontre comment AWK peut être utilisé pour des tâches d'analyse de données plus complexes. Vous pouvez étendre ce script pour inclure des statistiques supplémentaires ou différentes visualisations en fonction de vos besoins spécifiques.
Résumé
Félicitations ! Vous avez terminé ce laboratoire sur l'utilisation de la commande AWK pour l'analyse de journaux. Récapitulons ce que vous avez appris :
- Utilisation de base d'AWK : Impression de champs spécifiques à partir d'un fichier texte structuré.
- Filtrage des données : Utilisation de conditions dans AWK pour sélectionner des entrées de journal spécifiques.
- Comptage et synthèse : Utilisation d'AWK pour générer des statistiques à partir de données de journal.
- Création de rapports : Écriture de scripts AWK plus complexes pour générer des rapports formatés.
Ces compétences seront inestimables pour analyser des fichiers journaux, traiter des données et générer des rapports dans votre futur travail d'administrateur système ou d'analyste de données.
Voici quelques paramètres et fonctionnalités AWK supplémentaires que nous n'avons pas abordés dans ce laboratoire :
-F: Spécifie un séparateur de champ autre que l'espace.-v: Assigne une valeur à une variable.NR: Une variable intégrée représentant le numéro de l'enregistrement actuel.NF: Une variable intégrée représentant le nombre de champs dans l'enregistrement actuel.- Blocs
BEGINetEND: Motifs spéciaux pour l'initialisation et la finalisation. - Fonctions intégrées : Fonctions mathématiques, fonctions de chaîne, et plus encore.
N'oubliez pas que la pratique est la clé pour maîtriser AWK. Essayez de modifier les commandes et les scripts de ce laboratoire pour analyser différents aspects du fichier journal ou pour traiter d'autres types de données textuelles structurées.



