Steve Frécinaux

Pipe du diable

Voici un petit script shell écrit rapidement pour récupérer ses référents à partir des logs apache. Il récupère tous les liens dans le fichier journal, enlève celles qui ne sont pas intéressantes, et les transforme en une page HTML. En fait, une seule ligne utile et des variables :

#!/bin/bash
BLACKLIST="(tw\.apinc\.org|tw\.o0o\.ch)"
PREPEND='<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><html><head><title>Referers</title></head><body><pre>'
APPEND='</pre></body></html>'

REFERERS=`zcat $@ | egrep -o '"http://(\\\"|[^" ])+"' | sort | uniq - | egrep -v "^\"http://$BLACKLIST($|/)" | sed -e 's/\&/\&amp;/g' -e 's/^"\(.*\)"$/<a href="\1">\1<\/a>/' -`
echo "$PREPEND$REFERERS$APPEND"

Rien de bien intéressant, mais l’occasion de présenter à ceux qui ne les connaissent pas certains outils en ligne de commande, très utiles pour réaliser rapidement de petites choses comme ce que je voulais faire cette fois.

Passons la définition des variables, après tout cette partie est simple. La seule qui mérite attention c’est la définition de REFERERS : sa valeur est le résultat de la ligne de commande. Le truc c’est que la ligne de commande est entourrée de ` (bakcquotes) plutôt que de guillemets simples ou doubles. Ensuite l’affichage final est simplement la concaténation des trois variables contenant les trois morceaux de la page.

La ligne de commande se présente sous la forme d’un tuyau, ou pipe en anglais : les commandes sont séparées par le symbole |, que l’on appelle aussi pipe en jargon unixien (je ne connais pas le vrai nom de ce caractère). Son effet est de rediriger la sortie de la commande de gauche vers l’entrée de la commande de droite. Une utilisation fréquente de cette fonctionnalité est de rediriger la sortie d’une commande vers un pager comme less, pour pouvoir la lire à l’aise, alors qu’elle aurait pu prendre plus d’espace que celui disponible dans le terminal (bref, on n’aurait pas pu lire le début !)

La première commande utilisée est zcat. Elle fait la même chose que cat, mais en décompressant les fichiers gzip au préalable. cat concatène les fichiers passés en arguments. $@ est une variable contenant l’argument du script shell, ce qui veut dire que si on appelle ./script.sh foo bar, la commande zcat sera appelée avec les arguments foo bar, donc elle décompressera ces deux fichiers et les concatènera avant de les afficher. Cependant elle n’affichera rien car le pipe redirigera la sortie vers la commande suivante, qui utilisera ces données plutôt que de les lire depuis un fichier.

egrep permet de récupérer les lignes contenant des données correspondant à l’expression régulière fournie en argument. L’option -o fait que l’on ne récupère en fait que la partie de la ligne correspondant au motif (pattern). On obtient donc une liste d’URLs entourrées de guillemets doubles.

sort trie les lignes résultantes par ordre alphabétique, uniq - supprime les doublons. On obtient alors une liste ordonnée dans laquelle chaque URL n’est présente qu’une seule fois.

Le deuxième appel à egrep se fait avec l’appel -v. Le comportement de la commande sera alors l’inverse du comportement habituel : les lignes correspondant au motif seront enlevées. Le motif est contenu dans la variable BLACKLIST. Ici, j’enlève toutes les URLs internes à mon site.

Le plus marrant, maintenant : l’éditeur de flux sed. Travaillant lui-aussi sur base d’expressions régulières, il va me permettre de remplacer un motif par un autre. D’abord pour mettre les entités & au bon endroit, ensuite pour remplacer chaque URL par un lien HTML. Il s’agit d’un outil offrant de nombreuses possibilités mais parfois un peu complexe à utiliser, quand on dépasse le simple remplacement. Enfin il existe toute une série de scripts existant pour les opérations les plus courantes. Pour des besoins plus complexes, utilisez Perl ou Python, c’est plus simple !

Pour utiliser le script, enregistrez-le dans un fichier (comme getreferers.sh par exemple), rendez-le exécutable chmod +x getreferers.sh) et appelez-le en fournissant en argument les fichiers log à traîter :

./getreferers.sh ~/stats/2005/07/*.gz > referers.html

Le caractère > permet de rediriger la sortie du script vers un fichier, en l’occurence le fichier referers.html. Ça marche très bien pour les logs APINC pour peu que vous les ayez téléchargé préalablement depuis votre compte FTP, et ça a l’avantage de conserver les requêtes, contrairement à Webdruid.