Si vous avez besoin d’analyser des logs Squid, plusieurs moyens s’offrent à vous : l’antique SARG (Squid Analysis Report Generator), lightSquid, squid-analyser ou free-SA. Celui-ci est écrit en C et est à compiler. Il présente une commande simple d’utilisation, mais surtout une rapidité d’exécution par rapport à SARG.

Il présente toutefois un défaut, c’est un outil brut. On lui donne le fichier de log de Squid, un scope de dates et il génère un rapport de statistiques en html. Dans mon cas, j’ai besoin de traiter plusieurs fichiers, parfois compressés en gzip, parfois plusieurs fichiers à la fois. Free-SA ne le gère pas à la base, mais il y a moyen de l’implémenter via un script. En plus de cela j’ai une centralisation des logs de plusieurs proxy Squid (gérés par Syslog-ng). Je dois donc gérer tout cela de manière efficace.

Free-sa

Free-sa doit être compilé, pour cela, allez récupérer les sources de free-sa. Si quelqu’un à pris la peine de faire un paquet Deb d’installation, j’ajouterai volontiers son lien.

Installation

Paquets nécessaires à la compilation :

# apt-get install apache2 build-essential devscripts dh-make

Il n’y a pas de configuration pour Debian, mais on se base sur celle d’Ubuntu.

La configuration pour Debian a été publiée sur leur site : http://sourceforge.net/p/free-sa/patches/8/attachment/debian-i586-gcc4.mk, elle est à mettre dans le dossier « configs/ ».

Ensuite il faut éditer le fichier car on est dans une archi amd64 :

# cd configs/
# cp debian-i586-gcc4.mk debian-amd64-gcc4.mk

Remplacer :

SARCH = x86-64

Éditer global.mk pour utiliser ce fichier de conf :

OSTYPE = debian-amd64-gcc4

Et on compile…

# make && make install

Attention sur Debian Wheezy 7.3 64 bits on utilise gcc-4.7 dans mon cas.

  • Fichiers de conf dans : /etc/free-sa
  • Ajout de man : /usr/man
  • Ajout de share : /usr/share/
  • Ajout de cgi-bin dans : /var/www/free-sa
  • Et doc dans : /usr/share/doc/free-sa-1.6.2
  • Binaire : /usr/bin/free-sa

Utilisation

Voici un exemple d’arguments :

# /usr/bin/free-sa -f /etc/free-sa/server.conf -d $(date +%x)-
# /usr/bin/free-sa -f /etc/free-sa/server.conf -d 20/01/14-21/01/14

Performances

Voici les performances d’un test effectué avec un log journalier de Squid de 215Mo (~1millions de lignes) :

  • Le fichier a été traité en 15s
  • 184Mo de fichiers web créés.

 

Script de génération automatique d’analyse

Un script a été créé pour générer les rapports des proxy distant automatiquement. Pour cela il faut d’abord configurer Syslog-ng pour récupérer tous les logs sur votre serveur dédié à l’analyse des logs. Ce script s’occupe de tout :

  • Création des répertoires nécessaires pour stocker les analyses web s’ils n’existent pas
  • Copie d’une configuration free-sa « template » pour un nouveau serveur si elle n’existe pas
  • Création d’un fichier FIFO associé à un serveur s’il n’existe pas
  • L’ajout d’un proxy dans la page d’index se fait automatiquement car cette page liste tous les dossiers présents (avec gestion d’exclusion)
  • Alimenter le fichier FIFO avec les différents fichiers de logs, et cela selon les dates des fichiers afin de limiter la durée du « parsing » du fichier FIFO par free-sa.
  • Lancer free-sa avec le fichier de configuration associé.

 

#!/bin/bash
# Auteur : Belgotux
# Site : www.monlinux.net
# Adresse : 
# Version : 1.1
# Date : 21/01/2014
# Description : 
# Licence : GNU General Public License (GPL), version 3 (https://www.gnu.org/licenses/gpl.html)

#$1 host
#$2 time_range : options from free-sa
# Can be : 20/01/14-21/01/14
# also use next words as PERIODWORD: hour, day, week, month, quarter, year, today, yesterday, thisweek, lastweek, thismonth, lastmonth, thisyear, lastyear



## Check args
if [ "$#" != 2 ] || [ "$1" == "" ] ; then
    echo "$(basename $0) HOST TIME_RANGE"
    exit 1
fi
## Variables
host="$1"                            #don't edit
time_range="$2"                        #don't edit
max_range_day="35"                    #max periode days for free-sa analyse (use to reduce execution time)
CONFFILE="/etc/free-sa/$host.conf"    #don't edit
proxy_log_patern="/var/log/EXT/$host/squid-access.log"    #don't edit
conf_template_file="/etc/free-sa/template.conf"            #template config file to use for config's host generation
web_template_dir="/var/www/free-sa-template"            #template empty free-sa web structure


if [ ! -e "$CONFFILE" ] ; then
    sed -e "s/template/$host/g" "$conf_template_file" > "$CONFFILE" && echo "WARNING: Create CONFFILE $CONFFILE" || (echo "ERROR : no CONFFILE $CONFFILE present" >&2 && exit 1)
fi

#sed -ne 's#^ *log_file= *\(.*\)$#\1#p' /etc/free-sa/bruxelles.conf
. $CONFFILE

#test si la configuration web est présente
if [ ! -d "$web_template_dir" ] ; then
    echo "Error no template dir to use $web_template_dir" >&2 && exit 1
fi
    
if [ ! -d "$target_directory" ] ; then
    cp -r "$web_template_dir" "$target_directory" && echo "WARNING: Copy web template $web_template_dir to $target_directory" || (echo "ERROR : Impossible to copy web template $web_template_dir to $target_directory" >&2 && exit 1)
fi

#tester présence du cache
if [ ! -d "$cache_directory" ] ; then
    mkdir "$cache_directory" && echo "WARNING: Create cache directory $cache_directory" || (echo "ERROR : Impossible to create cache directory $cache_directory" >&2 && exit 1)
fi

#test if fifo exist
if [ ! -p "$log_file" ] ; then
    mkfifo -m 0600 "$log_file" && echo "WARNING: Create FIFO file $log_file" || (echo "ERROR : Impossible to create FIFO $log_file" >&2 && exit 1)
fi

#Récupération de tous des fichiers ayant une date dans le scoope et création de la FIFO
# Un * pour fifo fonctionne mais pas pour free-sa : zcat -f /var/log/EXT/bruxelles/squid-access.log* > /var/cache/free-sa/bruxelles.pipe
#Surement car les fichiers doivent être placés dans le bon ordre de date! Donc classé par date de fichiers plus vieux --> plus jeune
if [ "$max_range_day" != "" ] ; then
    listFiles=$(ls -trR1 /var/log/EXT/$host/squid-access.log* | tail -n $max_range_day)
else
    listFiles=$(ls -trR1 /var/log/EXT/$host/squid-access.log*)
fi
zcat -f $(echo $listFiles) > "$log_file" &
#zcat -f $(ls -trR /var/log/EXT/$host/squid-access.log*) > "$log_file" &

/usr/bin/free-sa -f $CONFFILE -d $time_range

exit $?

Exemple d’exécution :

$/usr/local/sbin/free-sa-genere-report.sh server yesterday
$/usr/local/sbin/free-sa-genere-report.sh server 20/01/14-21/01/14

Le script prend en paramètre le même format de temps que Free-sa. Il a été conçu pour être utilisé dans des crontab.

Crontab

Pour rajouter un nouveau serveur, ayant ses logs exportés sur le serveur centralisé, il suffit de rajouter une ligne dans les tâches cron et tout sera automatiquement créé. Voici un exemple :

Fichier /etc/cron.d/free-sa
#Every open-day 
30 0 * * 1-5    root    /usr/local/sbin/free-sa-genere-report.sh server yesterday 
#Every week 
30 1 * * 1    root    /usr/local/sbin/free-sa-genere-report.sh server lastweek 
#Every month 
30 2 1 * *    root    /usr/local/sbin/free-sa-genere-report.sh server lastmonth

 

Page PHP d’index

Voici la page PHP d’index que j’utilise pour lister les sous-répertoires free-SA.

<!DOCTYPE html>
<?php
$exclude_list = array(".", "..", "free-sa-template", "index.php","lost+found");
if (isset($_GET["dir"])) {
  $dir_path = $_SERVER["DOCUMENT_ROOT"]."/".$_GET["dir"];
}
else {
  $dir_path = $_SERVER["DOCUMENT_ROOT"]."/";
}
//-- until here
function dir_nav() {
  global $exclude_list, $dir_path;
  $directories = array_diff(scandir($dir_path), $exclude_list);
  echo "<ul style='list-style:none;padding:0'>";
  foreach($directories as $entry) {
    if(is_dir($dir_path.$entry)) {
      echo "<li style='margin-left:1em;'>[`] <a href='?dir=".$_GET["dir"].$entry."/"."'>".$entry."</a></li>";
    }
  }
  echo "</ul>";
  //-- separator
  echo "<ul style='list-style:none;padding:0'>";
  foreach($directories as $entry) {
    if(is_file($dir_path.$entry)) {
      echo "<li style='margin-left:1em;'>[ ] <a href='?file=".$_GET["dir"].$entry."'>".$entry."</a></li>";
    }
  }
  echo "</ul>";
}

function list_dir() {
  global $exclude_list, $dir_path;
  $directories = array_diff(scandir($dir_path), $exclude_list);
  echo "<ul style='list-style:none;padding:0'>";
  foreach($directories as $entry) {
      echo "<p> <a href='".$entry."/"."'>".$entry."</a></p>";
  }

}


?>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Projects</title>
    <style type="text/css">
        body{
            background: #E6E6E6;
            font-family: Helvetica;
        }
        #wrapper{
            width: 620px;
            margin: 20px auto;
        }
        #logo{
            width: 620px;
            background:#3300FF;
            margin: 20px 0;
            padding: 0px 20px;
            -moz-border-radius: 10px;                //bords ronds
            -moz-box-shadow: 5px 5px 5px #999;        //ombres
        }
        #page{
            width: 620px;
            min-height: 415px;
            background: #fff;
            margin: 20px 0;
            padding: 10px 20px;
            -webkit-border-radius: 10px;
            -webkit-box-shadow: 5px 5px 5px #999;
            -moz-border-radius: 10px;                //bords ronds
            -moz-box-shadow: 5px 5px 5px #999;        //ombres
        }
        #phpinfo{
            display: none;
            width: 620px;
            min-height: 215px;
            background: #fff;
            
            margin: 20px 0;
            padding: 10px 20px;
            -webkit-border-radius: 10px;
            -webkit-box-shadow: 5px 5px 5px #999;
            -moz-border-radius: 10px;                //bords ronds
            -moz-box-shadow: 5px 5px 5px #999;        //ombres
        }

        a span {
            display:none;
        }
        a:hover span {
            display:block;
        }
        h1{
            font-size: 32px;
            color: #fff;
            padding:5px 0 5px 0;
        }
        h2{
            font-size: 24px;
            color: #3300FF;
            margin: 10px 0 15px 0;
        }
        p{
            margin: 10px 25px;
        }
        a{
            color: #4D4D4D;
            text-decoration: none;
            font-weight: bold;
        }
        a:hover{
            text-decoration: un#phpinfoderline;
            color: #3300FF;
        }
        a.small{
            font-size: 12px;
        }
        ul{
            font-size: 12px;
        }
        ul li{
            margin: 0 0 5px 0;
        }
        ul li .bold{
            font-weight: bold;
        }
        img{
        border:0;
        }
        .people{
            background: #fff;
            padding: 10px;
            -webkit-border-radius: 5px;
            -moz-border-radius: 5px;
            margin-bottom: 26px;
            -webkit-box-shadow: margin: 20px 0;3px 3px 3px #999;
            -moz-box-shadow: 3px 3px 3px #999;
        }
    </style>
</head>
<body>
<div id="wrapper">
    <div id="logo">
        <h1>EXAMPLE</h1>
    </div>
    <div id="page">
        <h2>Servers lists</h2>
        <?php
        list_dir();
        //-- optional placement
        if (isset($_GET["file"])) {
          echo "<div style='margin:1em;border:1px solid Silver;'>";
          highlight_file($dir_path.$_GET['file']);
          echo "</div>";
        }
    
        ?>
    </div>        
        
</div>
</body>
</html>